Re: [HACKERS] Serializable lock consistency (was Re: CommitFest wrap-up)

2010-12-19 Thread Florian Pflug
On Dec19, 2010, at 18:06 , Heikki Linnakangas wrote:
> I think this patch is in pretty good shape now.
Apart from the serious deficiency Robert found :-(

I'll still comment on your suggestions though, since
they'd also apply to the solution I suggested on the
other thread.

> The one thing I'm not too happy with is the API for 
> heap_update/delete/lock_tuple. The return value is:
> 
> 
> 
> That's quite complicated. I think we should bite the bullet and add a couple 
> of more return codes to explicitly tell the caller what happened. I propose:

Yeah, it's a bit of a mess. On the other hand, heap_{update,delete,lock_tuple} 
are only called from very few places (simple_heap_update, simple_heap_delete, 
ExecUpdate, ExecLockRows and GetTupleForTrigger). Of these, only ExecUpdate and 
ExecLockRows care for update_xmax and ctid.

> HeapTupleMayBeUpdated- the tuple was actually updated (same as before)
> HeapTupleSelfUpdated - the tuple was updated by a later command in same xact 
> (same as before)
> HeapTupleBeingUpdated - concurrent update in progress (same as before)
> HeapTupleUpdated - the tuple was updated by another xact. *update_xmax and 
> *ctid are set to point to the replacement tuple.
> HeapTupleDeleted - the tuple was deleted by another xact
> HeapTupleLocked - lockcheck_snapshot was given, and the tuple was locked by 
> another xact

Hm, I'm not happy with HeapTupleMayBeUpdated meaning "The tuple was updated" 
while HeapTupleUpdated means "The tuple wasn't updated, a concurrent 
transaction beat us to it" seems less than ideal. On the whole, I'd much rather 
have a second enum, say HO_Result for heap operation result, instead of 
miss-using HTSU_Result for this. HO_Result would have the following possible 
values

HeapOperationCompleted - the tuple was updated/deleted/locked
HeapOperationSelfModified - the tuple was modified by a later command in the 
same xact. We don't distinguish the different cases here since none of the 
callers care.
HeapOperationBeingModified - the tuple was updated/deleted/locked (and the lock 
conflicts) by a transaction still in-progress.
HeapOperationConcurrentUpdate - the tuple was updated concurrently. 
*update_xmax and *ctid are set to point to the replacement tuple.
HeapOperationConcurrentDelete - the tuple was deleted concurrently.
HeapOperationConcurrentLock - the tuple was locked concurrently (only if 
lockcheck_snapshot was provided).

If we do want to keep heap_{update,delete,lock_tuple} result HTSU_Result, we 
could also add an output parameter of type HTSU_Failure with the possible values

HTSUConcurrentUpdate
HTSUConcurrentDelete
HTSUConcurrentLock

and set it accordingly if we return HeapTupleUpdated.

> I'm not sure how to incorporate that into the current 
> heap_delete/update/lock_tuple functions and HeapTupleSatisfiesUpdate. It 
> would be nice to not copy-paste the logic to handle those into all three 
> functions. Perhaps that common logic starting with the 
> HeapTupleSatisfiesUpdate() call could be pulled into a common function.


Hm, the logic in heap_lock_tuple is quite different from heap_delete and 
heap_update, since it needs to deal with share-mode lock acquisition. But for 
heap_{update,delete} unifying the logic should be possible.

best regards,
Florian Pflug


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] Serializable lock consistency (was Re: CommitFest wrap-up)

2010-12-19 Thread Heikki Linnakangas

On 17.12.2010 18:44, Florian Pflug wrote:

On Dec17, 2010, at 16:49 , Heikki Linnakangas wrote:

On 15.12.2010 16:20, Florian Pflug wrote:

On Dec14, 2010, at 15:01 , Robert Haas wrote:

On Tue, Dec 14, 2010 at 7:51 AM, Florian Pflug   wrote:

- serializable lock consistency - I am fairly certain this needs
rebasing.  I don't have time to deal with it right away.  That sucks,
because I think this is a really important change.

I can try to find some time to update the patch if it suffers from bit-rot. 
Would that help?


Yes!


I've rebased the patch to the current HEAD, and re-run my FK concurrency test 
suite,
available from https://github.com/fgp/fk_concurrency, to verify that things 
still work.

I've also asserts to the callers of heap_{update,delete,lock_tuple} to verify 
(and document)
that update_xmax may only be InvalidTransactionId if a lockcheck_snapshot is 
passed to
heap_{update,delete,lock_tuple}.

Finally, I've improved the explanation in src/backend/executor/README of how 
row locks and
REPEATABLE READ transactions interact, and tried to state the guarantees 
provided by
FOR SHARE and FOR UPDATE locks more precisely.

I've published my work to 
https://github.com/fgp/postgres/tree/serializable_lock_consistency,
and attached an updated patch. I'd be happy to give write access to that GIT 
repository
to anyone who wants to help getting this committed.


Here's some typo&  style fixes for that, also available at 
git://git.postgresql.org/git/users/heikki/postgres.git.


Thanks! FYI, I've pulled these into 
https://github.com/fgp/postgres/tree/serializable_lock_consistency


I think this patch is in pretty good shape now.

The one thing I'm not too happy with is the API for 
heap_update/delete/lock_tuple. The return value is:


 * Normal, successful return value is HeapTupleMayBeUpdated, which
 * actually means we *did* update it.  Failure return codes are
 * HeapTupleSelfUpdated, HeapTupleUpdated, or HeapTupleBeingUpdated
 * (the last only possible if wait == false).

And:

 * In the failure cases, the routine returns the tuple's t_ctid and t_max
 * in ctid and update_xmax.
 * If ctid is the same as t_self and update_xmax a valid transaction id,
 *  the tuple was deleted.
 * If ctid differs from t_self, the tuple was updated, ctid is the location
 *	of the replacement tuple and update_xmax is the updating 
transaction's xid.
 *	update_xmax must in this case be used to verify that the replacement 
tuple

 *  matched.
 * Otherwise, if ctid is the same as t_self and update_xmax is
 *  InvalidTransactionId, the tuple was neither replaced nor deleted, but
 *  locked by a transaction invisible to lockcheck_snapshot. This case can
 *  thus only arise if lockcheck_snapshot is a valid snapshot.

That's quite complicated. I think we should bite the bullet and add a 
couple of more return codes to explicitly tell the caller what happened. 
I propose:


HeapTupleMayBeUpdated- the tuple was actually updated (same as before)
HeapTupleSelfUpdated - the tuple was updated by a later command in same 
xact (same as before)

HeapTupleBeingUpdated - concurrent update in progress (same as before)
HeapTupleUpdated - the tuple was updated by another xact. *update_xmax 
and *ctid are set to point to the replacement tuple.

HeapTupleDeleted - the tuple was deleted by another xact
HeapTupleLocked - lockcheck_snapshot was given, and the tuple was locked 
by another xact


I'm not sure how to incorporate that into the current 
heap_delete/update/lock_tuple functions and HeapTupleSatisfiesUpdate. It 
would be nice to not copy-paste the logic to handle those into all three 
functions. Perhaps that common logic starting with the 
HeapTupleSatisfiesUpdate() call could be pulled into a common function.


--
  Heikki Linnakangas
  EnterpriseDB   http://www.enterprisedb.com

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] Serializable lock consistency (was Re: CommitFest wrap-up)

2010-12-17 Thread Florian Pflug
On Dec17, 2010, at 16:49 , Heikki Linnakangas wrote:
> On 15.12.2010 16:20, Florian Pflug wrote:
>> On Dec14, 2010, at 15:01 , Robert Haas wrote:
>>> On Tue, Dec 14, 2010 at 7:51 AM, Florian Pflug  wrote:
> - serializable lock consistency - I am fairly certain this needs
> rebasing.  I don't have time to deal with it right away.  That sucks,
> because I think this is a really important change.
 I can try to find some time to update the patch if it suffers from 
 bit-rot. Would that help?
>>> 
>>> Yes!
>> 
>> I've rebased the patch to the current HEAD, and re-run my FK concurrency 
>> test suite,
>> available from https://github.com/fgp/fk_concurrency, to verify that things 
>> still work.
>> 
>> I've also asserts to the callers of heap_{update,delete,lock_tuple} to 
>> verify (and document)
>> that update_xmax may only be InvalidTransactionId if a lockcheck_snapshot is 
>> passed to
>> heap_{update,delete,lock_tuple}.
>> 
>> Finally, I've improved the explanation in src/backend/executor/README of how 
>> row locks and
>> REPEATABLE READ transactions interact, and tried to state the guarantees 
>> provided by
>> FOR SHARE and FOR UPDATE locks more precisely.
>> 
>> I've published my work to 
>> https://github.com/fgp/postgres/tree/serializable_lock_consistency,
>> and attached an updated patch. I'd be happy to give write access to that GIT 
>> repository
>> to anyone who wants to help getting this committed.
> 
> Here's some typo & style fixes for that, also available at 
> git://git.postgresql.org/git/users/heikki/postgres.git.

Thanks! FYI, I've pulled these into 
https://github.com/fgp/postgres/tree/serializable_lock_consistency

best regards,
Florian Pflug



-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


[HACKERS] Serializable lock consistency (was Re: CommitFest wrap-up)

2010-12-17 Thread Heikki Linnakangas

On 15.12.2010 16:20, Florian Pflug wrote:

On Dec14, 2010, at 15:01 , Robert Haas wrote:

On Tue, Dec 14, 2010 at 7:51 AM, Florian Pflug  wrote:

- serializable lock consistency - I am fairly certain this needs
rebasing.  I don't have time to deal with it right away.  That sucks,
because I think this is a really important change.

I can try to find some time to update the patch if it suffers from bit-rot. 
Would that help?


Yes!


I've rebased the patch to the current HEAD, and re-run my FK concurrency test 
suite,
available from https://github.com/fgp/fk_concurrency, to verify that things 
still work.

I've also asserts to the callers of heap_{update,delete,lock_tuple} to verify 
(and document)
that update_xmax may only be InvalidTransactionId if a lockcheck_snapshot is 
passed to
heap_{update,delete,lock_tuple}.

Finally, I've improved the explanation in src/backend/executor/README of how 
row locks and
REPEATABLE READ transactions interact, and tried to state the guarantees 
provided by
FOR SHARE and FOR UPDATE locks more precisely.

I've published my work to 
https://github.com/fgp/postgres/tree/serializable_lock_consistency,
and attached an updated patch. I'd be happy to give write access to that GIT 
repository
to anyone who wants to help getting this committed.


Here's some typo & style fixes for that, also available at 
git://git.postgresql.org/git/users/heikki/postgres.git.


--
  Heikki Linnakangas
  EnterpriseDB   http://www.enterprisedb.com
diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index a397bad..3b12aca 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -2034,8 +2034,8 @@ simple_heap_insert(Relation relation, HeapTuple tup)
  *	cid - delete command ID (used for visibility test, and stored into
  *		cmax if successful)
  *	wait - true if should wait for any conflicting update to commit/abort
- *	lockcheck_snapshot - if not InvalidSnapshot, report the tuple as updated if it
- *		was once locked by a transaction not visible under this snapshot
+ *	lockcheck_snapshot - if not InvalidSnapshot, report the tuple as updated
+ *		if it was once locked by a transaction not visible under this snapshot
  *
  * Normal, successful return value is HeapTupleMayBeUpdated, which
  * actually means we did delete it.  Failure return codes are
@@ -2046,14 +2046,14 @@ simple_heap_insert(Relation relation, HeapTuple tup)
  * in ctid and update_xmax.
  * If ctid is the same as t_self and update_xmax a valid transaction id,
  *	the tuple was deleted.
- * If ctid differes from t_self, the tuple was updated, ctid is the location
- *	of the replacement tupe and update_xmax is the updating transaction's xid.
+ * If ctid differs from t_self, the tuple was updated. ctid is the location
+ *	of the replacement tuple and update_xmax is the updating transaction's xid.
  *	update_xmax must in this case be used to verify that the replacement tuple
  *	matched.
  * Otherwise, if ctid is the same as t_self and update_xmax is
- *	InvalidTranactionId, the tuple was neither replaced nor deleted, but locked
- *	by a transaction invisible to lockcheck_snapshot. This case can thus only
- *	arise if lockcheck_snapshot is a valid snapshot.
+ *	InvalidTransactionId, the tuple was neither replaced nor deleted, but
+ *	locked by a transaction invisible to lockcheck_snapshot. This case can
+ *	thus only arise if lockcheck_snapshot is a valid snapshot.
  */
 HTSU_Result
 heap_delete(Relation relation, ItemPointer tid,
@@ -2180,7 +2180,8 @@ l1:
 			result = HeapTupleUpdated;
 	}
 
-	/* If the tuple was updated, we report the updating transaction's
+	/*
+	 * If the tuple was updated, we report the updating transaction's
 	 * xid in update_xmax. Otherwise, we must check that it wasn't
 	 * locked by a transaction invisible to lockcheck_snapshot before
 	 * continuing.
@@ -2368,9 +2369,9 @@ simple_heap_delete(Relation relation, ItemPointer tid)
  *	update_xmax - output parameter, used only for failure case (see below)
  *	cid - update command ID (used for visibility test, and stored into
  *		cmax/cmin if successful)
+ *	wait - true if should wait for any conflicting update to commit/abort
  *	lockcheck_snapshot - if not InvalidSnapshot, report the tuple as updated
  *		if it was once locked by a transaction not visible under this snapshot
- *	wait - true if should wait for any conflicting update to commit/abort
  *
  * Normal, successful return value is HeapTupleMayBeUpdated, which
  * actually means we *did* update it.  Failure return codes are
@@ -2387,14 +2388,14 @@ simple_heap_delete(Relation relation, ItemPointer tid)
  * in ctid and update_xmax.
  * If ctid is the same as t_self and update_xmax a valid transaction id,
  *	the tuple was deleted.
- * If ctid differes from t_self, the tuple was updated, ctid is the location
- *	of the replacement tupe and update_xmax is the updating transaction's xid.
+ * If ctid differs from t_self, the tuple was updated, ctid is th