What is a snapshot

From: Alvaro Herrera <alvherre(at)dcc(dot)uchile(dot)cl>
To: Hackers <pgsql-hackers(at)postgresql(dot)org>
Subject: What is a snapshot
Date: 2003-05-11 23:29:27
Message-ID: 20030511232926.GB10614@dcc.uchile.cl
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

Hackers,

Clearly it's not going to help to all the nested transactions project if
we don't make clear the concept of a snapshot.

In the current implementation, it's sufficient to know
a) what transactions come before me (Xmin),
b) what transactions come after me (Xmax),
c) what transactions are in progress (xip), and
d) what commands come before me in the current transaction
(curcid)

In the nested transactions case, we also need to know

e) what subtransactions of my own parent transactions come before me,
and
f) what commands of my parent transactions come before me.

Consider the following scenario:

BEGIN; xid=1
CREATE TABLE a (p int UNIQUE, q int); xid=1 cid=1
INSERT INTO a (p) VALUES (1); xid=1 cid=2
BEGIN; xid=2
-- should fail due to unique constraint
INSERT INTO a (p) VALUES (1); xid=2 cid=1
ROLLBACK;
BEGIN; xid=3
INSERT INTO a (p) VALUES (2); cid=1
DELETE FROM a WHERE one=1; cid=2
-- "a" should have 1 tuple
COMMIT;
-- should work, because the old tuple doesn't exist anymore
INSERT INTO a (p) VALUES (1); xid=1 cid=3
COMMIT;

Here, the QuerySnapshot of xid 1, at the time of cid=3 should see the
results of execution from xid 3, but it is not before Xmin, and it's
after Xmax, and is not in the xip array.

Also, the QuerySnapshot of xid 3, should see the results of commands
from xid 1 just like they'd be seen if they where in the same xact but
with a lesser CommandId.

Both cases are not implementable with the current notion of a Snapshot.

I propose that the SnapshotData struct is expanded as:

typedef struct SnapshotData
{
TransactionId xmin; /* XID < xmin are visible to me */
TransactionId xmax; /* XID >= xmax are invisible to me */
uint32 xcnt; /* # of xact ids in xip[] */
TransactionId *xip; /* array of xact IDs in progress */
/* note: all ids in xip[] satisfy xmin <= xip[i] < xmax */
CommandId curcid; /* in my xact, CID < curcid are visible */
ItemPointerData tid; /* required for Dirty snapshot -:( */
/* new members below */
uint32 childcnt; /* # of xact ids in childcnt[] */
TransactionId *childxact; /* array of completed child xact IDs */
uint32 parentcnt; /* # of xact ids in parentcnt[] */
TransactionId *parentxact; /* array of parent xact IDs */
} SnapshotData;

And then we will have to rewrite the HeapTupleSatisfies* routines to act
according to this new Snapshot structure, and also with the pg_subtrans
mechanism to know which subtransactions were aborted.

When starting a subtransaction, the child will have the parent's XID in
parentxact, and all the XID's the parent has in parentxact as well.
When ending a subtransaction, the parent will record its XID in
childxact, and all the XID's the child had in childxact.

It's not necessary to keep the parent's CommandId, because there are no
future CommandIds recorded in any tuple (no need to check).

I'm not sure what the SerializableSnapshot should be. It does need to
take into account the changes made by previous committed
subtransactions, right?

It's also clear that we need to differentiate a parent's QuerySnapshot
from their child's. It's not clear to me what should be done in the
case of a SerializableSnapshot.

--
Alvaro Herrera (<alvherre[a]dcc.uchile.cl>)
"The Postgresql hackers have what I call a "NASA space shot" mentality.
Quite refreshing in a world of "weekend drag racer" developers."
(Scott Marlowe)

Browse pgsql-hackers by date

  From Date Subject
Next Message Andrew Dunstan 2003-05-12 00:25:09 Re: Plans for index names unique to a table?
Previous Message Tom Lane 2003-05-11 22:50:36 Re: 7.3 and HEAD broken for dropped columns of dropped types