Re: Autonomous Transaction is back - Mailing list pgsql-hackers

From Merlin Moncure
Subject Re: Autonomous Transaction is back
Date
Msg-id CAHyXU0xOLN6V7b_x3-_zsRhQx7viyJieZ2ZMd8CAJu_rYqMLpA@mail.gmail.com
Whole thread Raw
In response to Re: Autonomous Transaction is back  (Robert Haas <robertmhaas@gmail.com>)
Responses Re: Autonomous Transaction is back  (Robert Haas <robertmhaas@gmail.com>)
List pgsql-hackers
On Thu, Aug 6, 2015 at 4:15 PM, Robert Haas <robertmhaas@gmail.com> wrote:
> On Mon, Aug 3, 2015 at 9:09 AM, Merlin Moncure <mmoncure@gmail.com> wrote:
>> hm.  OK, what's the behavior of:
>>
>> BEGIN
>>   UPDATE foo SET x = x + 1 WHERE foo_id = 1;
>>
>>   BEGIN WITH AUTONOMOUS TRANSACTION
>>     UPDATE foo SET x = x + 1 WHERE foo_id = 1;
>>   END;
>>
>>   RAISE EXCEPTION ...;
>> EXCEPTION ...
>>
>> END;
>
> Sure, so that case might need a little bit of special handling.  That
> doesn't mean it's a good idea for heavyweight locks to conflict in
> general.  I think you're going to find that implementing the latter is
> an extremely unrewarding task, and that the benefits are seriously
> negative.  For example, consider:
>
> BEGIN
> UPDATE foo SET x = x + 1 WHERE foo_id = 1;
> BEGIN WITH AUTONOMOUS TRANSACTION
> UPDATE foo SET x = x + 1 WHERE foo_id = 2;
> END;
> END;
>
> Now, suppose that a concurrent session does LOCK TABLE foo after the
> first UPDATE and before the second one.  That's now a soft deadlock.
> But the only way the deadlock detector can see that is if the main
> transaction and the autonomous transaction have separate PGPROC
> entries, which is a design we explicitly rejected because it puts a
> tight limit on the number of ATs that can be in progress and the level
> to which those ATs can be nested.  But let's say you don't care, so we
> go back to that design.  The deadlock detector will have to be taught
> that the outer transaction can't help but wait for the inner
> transaction, so we teach it that.  Now it can see that the only way to
> resolve the deadlock without aborting any transactions is to reorder
> the lock request from the autonomous transaction ahead of the
> concurrent session that is seeking a full table lock.  So the
> autonomous transaction acquires the lock without blocking after all.
> You have exactly the same result that you would have had anyway but
> with a phenomenal amount of additional code and complexity.
>
> And for what?  In the original example, the way the deadlock is going
> to be reported is like this:
>
> ERROR: deadlock detected
> DETAIL: Process 12345 waits for ShareLock on transaction 1000; blocked
> by process 12345.
> Process 12345 waits for ShareLock on transaction 1001; blocked by process 12345.
>
> That is not a model of clarity.  On the other hand, if you just make a
> rule that attempting to update or delete a tuple that an outer
> transaction has already updated throws a bespoke error, you can do
> something like this:
>
> ERROR: tuple to be updated was already modified by a suspended outer transaction
>
> ...which has precedent in an existing message in trigger.c.
> Similarly, if you try to drop a table that the outer transaction has
> locked, the natural thing is for CheckTableNotInUse() to catch that
> and report it this way:
>
> ERROR: cannot DROP TABLE "foo" because it is being used by active
> queries in this session
>
> If you work hard enough, you can instead make that generate a deadlock
> error message, but you're going to have to work pretty hard, and the
> result is worse.
>
> I'd really like to hear some more *specific* scenarios where it's
> valuable for locks to conflict between the outer transaction and the
> AT.  I grant that tuple updates are a case where the conflict has to
> be detected somehow, but I don't accept that the lock manager is the
> best way to do that, and I don't accept that there are a large number
> of other cases that will need similar handling.

I don't necessarily disagree with what you're saying, but it's not
clear to me what the proposed behavior is.  Since the AT can commit
before the outer, ISTM *any* ungranted lock requested by the AT but
held by the outer leads to either A: functional deadlock (regardless
of implementation details) or B: special behavior.  Deadlocks would
certainly require some acrobatics to detect and resolve due to the
fact that one party to the lock is not in fact blocked on a lock but
on the outer's execution state.  So maybe the right thing to do is to
simply ignore the problem and hang both transactions until timeout or
cancel; this isn't really much different vs. ghetto dblink style AT
that is done today in my experience.

merlin



pgsql-hackers by date:

Previous
From: Bruce Momjian
Date:
Subject: Re: 9.5 release notes
Next
From: Noah Misch
Date:
Subject: Re: Raising our compiler requirements for 9.6