Disable optimization when in subtransaction

Started by Kevin Grittneralmost 15 years ago2 messages
#1Kevin Grittner
Kevin.Grittner@wicourts.gov
1 attachment(s)

When I was investigating this report:

http://archives.postgresql.org/pgsql-bugs/2011-03/msg00349.php

besides providing a straightforward fix here:

http://archives.postgresql.org/pgsql-bugs/2011-03/msg00352.php

I noted that there was nearby code which needed review, as it didn't
seem safe when in a subtransaction. Further review confirmed this
and didn't turn up any other problems in that section of code. So,
a fix for this overreaching optimization is attached. Note that it
is a one-line fix except for some additional comments to explain the
limitation.

This patch is in addition to and orthogonal to the first patch cited
above.

I will add this one to the 9.1 open items list.

-Kevin

Attachments:

ssi-subtransaction-no-optimization.patchtext/plain; name=ssi-subtransaction-no-optimization.patchDownload
*** a/src/backend/storage/lmgr/predicate.c
--- b/src/backend/storage/lmgr/predicate.c
***************
*** 3635,3649 **** CheckTargetForConflictsIn(PREDICATELOCKTARGETTAG *targettag)
  						 offsetof(PREDICATELOCK, targetLink));
  
  		sxact = predlock->tag.myXact;
! 		if (sxact == MySerializableXact)
  		{
  			/*
! 			 * If we're getting a write lock on the tuple, we don't need a
! 			 * predicate (SIREAD) lock. At this point our transaction already
! 			 * has an ExclusiveRowLock on the relation, so we are OK to drop
! 			 * the predicate lock on the tuple, if found, without fearing that
! 			 * another write against the tuple will occur before the MVCC
! 			 * information makes it to the buffer.
  			 */
  			if (GET_PREDICATELOCKTARGETTAG_OFFSET(*targettag))
  			{
--- 3635,3654 ----
  						 offsetof(PREDICATELOCK, targetLink));
  
  		sxact = predlock->tag.myXact;
! 		if (sxact == MySerializableXact && !IsSubTransaction())
  		{
  			/*
! 			 * If we're getting a write lock on the tuple and we're not in a
! 			 * subtransaction, we don't need a predicate (SIREAD) lock.  We
! 			 * can't use this optimization within a subtransaction because
! 			 * the subtransaction could be rolled back, and we would be left
! 			 * without any lock at the top level.
! 			 * 
! 			 * At this point our transaction already has an ExclusiveRowLock
! 			 * on the relation, so we are OK to drop the predicate lock on
! 			 * the tuple, if found, without fearing that another write
! 			 * against the tuple will occur before the MVCC information
! 			 * makes it to the buffer.
  			 */
  			if (GET_PREDICATELOCKTARGETTAG_OFFSET(*targettag))
  			{
#2Kevin Grittner
Kevin.Grittner@wicourts.gov
In reply to: Kevin Grittner (#1)
1 attachment(s)
Re: Disable optimization when in subtransaction

"Kevin Grittner" <Kevin.Grittner@wicourts.gov> wrote:

When I was investigating this report:

http://archives.postgresql.org/pgsql-bugs/2011-03/msg00349.php

besides providing a straightforward fix here:

http://archives.postgresql.org/pgsql-bugs/2011-03/msg00352.php

I noted that there was nearby code which needed review, as it
didn't seem safe when in a subtransaction. Further review
confirmed this and didn't turn up any other problems in that
section of code. So, a fix for this overreaching optimization is
attached. Note that it is a one-line fix except for some
additional comments to explain the limitation.

This patch is in addition to and orthogonal to the first patch
cited above.

I will add this one to the 9.1 open items list.

I managed to get a one-line patch wrong. Sorry. 2nd try.

-Kevin

Attachments:

ssi-subtransaction-no-optimization-v2.patchtext/plain; name=ssi-subtransaction-no-optimization-v2.patchDownload
*** a/src/backend/storage/lmgr/predicate.c
--- b/src/backend/storage/lmgr/predicate.c
***************
*** 3638,3651 **** CheckTargetForConflictsIn(PREDICATELOCKTARGETTAG *targettag)
  		if (sxact == MySerializableXact)
  		{
  			/*
! 			 * If we're getting a write lock on the tuple, we don't need a
! 			 * predicate (SIREAD) lock. At this point our transaction already
! 			 * has an ExclusiveRowLock on the relation, so we are OK to drop
! 			 * the predicate lock on the tuple, if found, without fearing that
! 			 * another write against the tuple will occur before the MVCC
! 			 * information makes it to the buffer.
  			 */
! 			if (GET_PREDICATELOCKTARGETTAG_OFFSET(*targettag))
  			{
  				uint32		predlockhashcode;
  				PREDICATELOCKTARGET *rmtarget = NULL;
--- 3638,3657 ----
  		if (sxact == MySerializableXact)
  		{
  			/*
! 			 * If we're getting a write lock on the tuple and we're not in a
! 			 * subtransaction, we don't need a predicate (SIREAD) lock.  We
! 			 * can't use this optimization within a subtransaction because
! 			 * the subtransaction could be rolled back, and we would be left
! 			 * without any lock at the top level.
! 			 * 
! 			 * At this point our transaction already has an ExclusiveRowLock
! 			 * on the relation, so we are OK to drop the predicate lock on
! 			 * the tuple, if found, without fearing that another write
! 			 * against the tuple will occur before the MVCC information
! 			 * makes it to the buffer.
  			 */
! 			if (!IsSubTransaction()
! 				&& GET_PREDICATELOCKTARGETTAG_OFFSET(*targettag))
  			{
  				uint32		predlockhashcode;
  				PREDICATELOCKTARGET *rmtarget = NULL;