> > You forget about Tx Old! The point is that changes made by
> > Tx Old *over* Tx New' changes effectively make those Tx New'
> > changes *visible* to Tx S!
> 
> Yes, but what's that got to do with the order of operations in
> GetSnapshotData?  The scenario you describe can occur anyway.

Try to describe it step by step.

> Only if Tx Old is running in Read Committed mode, of course.
> But if it is, then it's capable of deciding to update a row updated
> by Tx New.  Whether Tx S's xmax value is before or after Tx New's ID
> is not going to change the behavior of Tx Old.

1.  I consider particular case when Tx S' xmax is before Tx New' ID.
1.1 For this case acquiring SInval lock before ReadNewTransactionId()
    changes behavior of Tx Old: it postpones change of Tx Old'
    (and Tx New') MyProc->xid in xact.c:CommitTransaction(), so Tx S
    will see Tx Old as running, ie Tx Old' changes will be invisible
    to Tx S on the base of analyzing MyProc.xid-s, just like Tx New'
    changes will be invisible on the base of analyzing next Tx ID.
2.  If you can find examples when current code is not able to provide
    consistent snapshot of running (out of interest) transactions
    let's think how to fix code. Untill then my example shows why
    we cannot move SInval lock request after ReadNewTransactionId().

> I'd still like to change GetSnapshotData to read the nextXid before
> it acquires SInvalLock, though.  If we did that, it'd be safe to make
> GetNewTransactionId be
> 
> 	SpinAcquire(XidGenLockId);
> 	xid = nextXid++;
> 	SpinAcquire(SInvalLockId);
> 	MyProc->xid = xid;
> 	SpinRelease(SInvalLockId);
> 	SpinRelease(XidGenLockId);
> 
> which is really necessary if you want to avoid assuming that
> TransactionIds can be fetched and stored atomically.

To avoid that assumption one should add per MyProc spinlock.

Vadim

Thu, 12 Jul 2001 10:11:02 -0700
"Mikheev, Vadim" <vmikheev@SECTORBASE.COM>
RE: Re: Strangeness in xid allocation / snapshot setup 
"Mikheev, Vadim" <vmikheev@SECTORBASE.COM> writes:
> 1.1 For this case acquiring SInval lock before ReadNewTransactionId()
>     changes behavior of Tx Old: it postpones change of Tx Old'
>     (and Tx New') MyProc->xid in xact.c:CommitTransaction(), so Tx S
>     will see Tx Old as running, ie Tx Old' changes will be invisible
>     to Tx S on the base of analyzing MyProc.xid-s, just like Tx New'
>     changes will be invisible on the base of analyzing next Tx ID.

Oh, now I get it: the point is to prevent Tx Old from exiting the set
of "still running" xacts as seen by Tx S.  Okay, it makes sense.
I'll try to add some documentation to explain it.

Given this, I'm wondering why we bother with having a separate
XidGenLock spinlock at all.  Why not eliminate it and use SInval
spinlock to lock GetNewTransactionId and ReadNewTransactionId?

What did you think about reordering the vacuum qual tests and
AbortTransaction sequence?

BTW, I'm starting to think that it would be really nice if we could
replace our spinlocks with not just a semaphore, but something that has
a notion of "shared" and "exclusive" lock requests.  For example,
if GetSnapshotData could use a shared lock on SInvalLock, it'd
improve concurrency.

			regards, tom lane

Thu, 12 Jul 2001 13:24:17 -0400
Tom Lane <tgl@sss.pgh.pa.us>
Re: Re: Strangeness in xid allocation / snapshot setup 