On Wed, 2008-10-22 at 21:47 +0100, Simon Riggs wrote:

> But once you reach 64 transactions, you'll need to write an extra WAL
> record for every subtransaction, which currently I've managed to avoid.

Some further notes/tests on the optimisation you discovered.

Because of the way I have changed tqual.c, we only need to write to
subtrans if a proc's subxid cache overflows. (I think we would need to
change tqual.c in a similar way in any of the ways so far discussed).

Anyway, quick test with a representative test case shows 3-5%
performance gain from skipping the subtrans updates. I only the test
case files here and the test patch. The test is a simple PL/pgSQL
function with one EXCEPTION clause, so fairly real world.

The patch isn't ready to apply standalone because we need to include the
changes to XidInMVCCSnapshot() also, which would take a little while to
extract. Let me know if that is worth producing a standalone patch for.

-- 
 Simon Riggs           www.2ndQuadrant.com
 PostgreSQL Training, Services and Support
SELECT new_order();

CREATE TABLE orders
(ordid	SERIAL NOT NULL PRIMARY KEY);

CREATE FUNCTION new_order() RETURNS VOID LANGUAGE PLPGSQL AS
$$
DECLARE
BEGIN
	INSERT INTO orders DEFAULT VALUES;
EXCEPTION
	WHEN unique_violation THEN
	--do nothing
END;
$$;
Index: src/backend/access/transam/varsup.c
===================================================================
RCS file: /home/sriggs/pg/REPOSITORY/pgsql/src/backend/access/transam/varsup.c,v
retrieving revision 1.81
diff -c -r1.81 varsup.c
*** src/backend/access/transam/varsup.c	1 Jan 2008 19:45:48 -0000	1.81
--- src/backend/access/transam/varsup.c	23 Oct 2008 04:36:04 -0000
***************
*** 36,44 ****
   * The new XID is also stored into MyProc before returning.
   */
  TransactionId
! GetNewTransactionId(bool isSubXact)
  {
! 	TransactionId xid;
  
  	/*
  	 * During bootstrap initialization, we return the special bootstrap
--- 36,45 ----
   * The new XID is also stored into MyProc before returning.
   */
  TransactionId
! GetNewTransactionId(TransactionId parentXid)
  {
! 	TransactionId 	xid;
! 	bool			isSubXact = TransactionIdIsValid(parentXid);
  
  	/*
  	 * During bootstrap initialization, we return the special bootstrap
***************
*** 176,181 ****
--- 177,191 ----
  
  	LWLockRelease(XidGenLock);
  
+ 	/*
+ 	 * NB: we must make the subtrans entry BEFORE the Xid appears anywhere in
+ 	 * shared storage other than PG_PROC; because if there's no room for it in
+ 	 * PG_PROC, the subtrans entry is needed to ensure that other backends see
+ 	 * the Xid as "running".
+ 	 */
+ 	if (isSubXact && MyProc->subxids.overflowed)
+ 		SubTransSetParent(xid, parentXid);
+ 
  	return xid;
  }
  
Index: src/backend/access/transam/xact.c
===================================================================
RCS file: /home/sriggs/pg/REPOSITORY/pgsql/src/backend/access/transam/xact.c,v
retrieving revision 1.266
diff -c -r1.266 xact.c
*** src/backend/access/transam/xact.c	20 Oct 2008 19:18:18 -0000	1.266
--- src/backend/access/transam/xact.c	23 Oct 2008 04:38:02 -0000
***************
*** 391,396 ****
--- 391,397 ----
  {
  	bool		isSubXact = (s->parent != NULL);
  	ResourceOwner currentOwner;
+ 	TransactionId parentXid = InvalidTransactionId;
  
  	/* Assert that caller didn't screw up */
  	Assert(!TransactionIdIsValid(s->transactionId));
***************
*** 404,420 ****
  		AssignTransactionId(s->parent);
  
  	/*
! 	 * Generate a new Xid and record it in PG_PROC and pg_subtrans.
! 	 *
! 	 * NB: we must make the subtrans entry BEFORE the Xid appears anywhere in
! 	 * shared storage other than PG_PROC; because if there's no room for it in
! 	 * PG_PROC, the subtrans entry is needed to ensure that other backends see
! 	 * the Xid as "running".  See GetNewTransactionId.
  	 */
- 	s->transactionId = GetNewTransactionId(isSubXact);
- 
  	if (isSubXact)
! 		SubTransSetParent(s->transactionId, s->parent->transactionId);
  
  	/*
  	 * Acquire lock on the transaction XID.  (We assume this cannot block.) We
--- 405,415 ----
  		AssignTransactionId(s->parent);
  
  	/*
! 	 * Generate a new Xid and record it in PG_PROC and pg_subtrans, if required
  	 */
  	if (isSubXact)
! 		parentXid = s->parent->transactionId;
! 	s->transactionId = GetNewTransactionId(parentXid);
  
  	/*
  	 * Acquire lock on the transaction XID.  (We assume this cannot block.) We
Index: src/include/access/transam.h
===================================================================
RCS file: /home/sriggs/pg/REPOSITORY/pgsql/src/include/access/transam.h,v
retrieving revision 1.66
diff -c -r1.66 transam.h
*** src/include/access/transam.h	20 Oct 2008 19:18:18 -0000	1.66
--- src/include/access/transam.h	23 Oct 2008 04:37:04 -0000
***************
*** 152,158 ****
  extern XLogRecPtr TransactionIdGetCommitLSN(TransactionId xid);
  
  /* in transam/varsup.c */
! extern TransactionId GetNewTransactionId(bool isSubXact);
  extern TransactionId ReadNewTransactionId(void);
  extern void SetTransactionIdLimit(TransactionId oldest_datfrozenxid,
  					  Name oldest_datname);
--- 152,158 ----
  extern XLogRecPtr TransactionIdGetCommitLSN(TransactionId xid);
  
  /* in transam/varsup.c */
! extern TransactionId GetNewTransactionId(TransactionId parentXid);
  extern TransactionId ReadNewTransactionId(void);
  extern void SetTransactionIdLimit(TransactionId oldest_datfrozenxid,
  					  Name oldest_datname);
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to