On Thu, Jan 2, 2014 at 8:08 AM, Heikki Linnakangas
<hlinnakangas@vmware.com> wrote:
>> Yeah, it seems like PromiseTupleInsertionLockAcquire should be locking
>> the tuple, rather than the XID.
>
> Well, that would be ideal, because we already have tuple locks. It would be
> nice to use the same concept for this. It's a bit tricky, however. I guess
> the most straightforward way to do it would be to grab a heavy-weight lock
> after you've inserted the tuple, but before releasing the buffer lock. I
> don't immediately see a problem with that, although it's a bit scary to
> acquire a heavy-weight lock while holding a buffer lock.
That's a really big modularity violation. Everything after
RelationPutHeapTuple() but before the buffer unlock in heap_insert()
is currently critical section. I'm not saying that it can't be done,
but it certainly is scary.
We also have heavyweight page locks, currently used by hash indexes.
That approach does not require us to contort the row locking code, and
certainly does not require us to acquire heavyweight locks with buffer
locks already held. I could understand your initial disinclination to
doing things this way, particularly when the unprincipled deadlocking
problem was not well understood, but I think that this must tip the
balance in favor of the approach I advocate. What I've done with
heavyweight locks is a modest, localized, logical expansion on the
existing mechanism, that is easy to reason about, with room for
further optimization in the future, that still has reasonable
performance characteristics today, including I believe better
worst-case latency. Heavyweight locks on btree pages are very well
precedented, if you look beyond Postgres.
--
Peter Geoghegan