Search Postgresql Archives

Re: attempted to lock invisible tuple - PG 8.4.1

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Stuart Bishop wrote:

> >I don't think the committed patch touches anything involved in what
> >you're testing, but if you could grab CVS tip from the 8.4 branch (or
> >the snapshot from ftp.postgresql.org:/pub/snapshot/stable/8.4 ) and give
> >it a try, that'd be great.
> 
> I trigger the same error with a freshly built snapshot.

If you're up for a bit of patching, please test with the attached patch
applied.

-- 
Alvaro Herrera                                http://www.CommandPrompt.com/
The PostgreSQL Company - Command Prompt, Inc.
Index: src/backend/commands/portalcmds.c
===================================================================
RCS file: /home/alvherre/Code/cvs/pgsql/src/backend/commands/portalcmds.c,v
retrieving revision 1.79.2.1
diff -c -p -r1.79.2.1 portalcmds.c
*** src/backend/commands/portalcmds.c	2 Oct 2009 17:58:21 -0000	1.79.2.1
--- src/backend/commands/portalcmds.c	6 Oct 2009 19:54:21 -0000
*************** PerformCursorOpen(PlannedStmt *stmt, Par
*** 47,53 ****
  	DeclareCursorStmt *cstmt = (DeclareCursorStmt *) stmt->utilityStmt;
  	Portal		portal;
  	MemoryContext oldContext;
- 	Snapshot	snapshot;
  
  	if (cstmt == NULL || !IsA(cstmt, DeclareCursorStmt))
  		elog(ERROR, "PerformCursorOpen called for non-cursor query");
--- 47,52 ----
*************** PerformCursorOpen(PlannedStmt *stmt, Par
*** 120,136 ****
  	}
  
  	/*
- 	 * Set up snapshot for portal.  Note that we need a fresh, independent copy
- 	 * of the snapshot because we don't want it to be modified by future
- 	 * CommandCounterIncrement calls.  We do not register it, because
- 	 * portalmem.c will take care of that internally.
- 	 */
- 	snapshot = CopySnapshot(GetActiveSnapshot());
- 
- 	/*
  	 * Start execution, inserting parameters if any.
  	 */
! 	PortalStart(portal, params, snapshot);
  
  	Assert(portal->strategy == PORTAL_ONE_SELECT);
  
--- 119,127 ----
  	}
  
  	/*
  	 * Start execution, inserting parameters if any.
  	 */
! 	PortalStart(portal, params, GetActiveSnapshot());
  
  	Assert(portal->strategy == PORTAL_ONE_SELECT);
  
Index: src/backend/utils/time/snapmgr.c
===================================================================
RCS file: /home/alvherre/Code/cvs/pgsql/src/backend/utils/time/snapmgr.c,v
retrieving revision 1.10.2.1
diff -c -p -r1.10.2.1 snapmgr.c
*** src/backend/utils/time/snapmgr.c	2 Oct 2009 17:58:21 -0000	1.10.2.1
--- src/backend/utils/time/snapmgr.c	6 Oct 2009 19:54:21 -0000
*************** bool		FirstSnapshotSet = false;
*** 104,109 ****
--- 104,110 ----
  static bool registered_serializable = false;
  
  
+ static Snapshot CopySnapshot(Snapshot snapshot);
  static void FreeSnapshot(Snapshot snapshot);
  static void SnapshotResetXmin(void);
  
*************** SnapshotSetCommandId(CommandId curcid)
*** 191,197 ****
   * The copy is palloc'd in TopTransactionContext and has initial refcounts set
   * to 0.  The returned snapshot has the copied flag set.
   */
! Snapshot
  CopySnapshot(Snapshot snapshot)
  {
  	Snapshot	newsnap;
--- 192,198 ----
   * The copy is palloc'd in TopTransactionContext and has initial refcounts set
   * to 0.  The returned snapshot has the copied flag set.
   */
! static Snapshot
  CopySnapshot(Snapshot snapshot)
  {
  	Snapshot	newsnap;
*************** FreeSnapshot(Snapshot snapshot)
*** 254,261 ****
   * PushActiveSnapshot
   *		Set the given snapshot as the current active snapshot
   *
!  * If this is the first use of this snapshot, create a new long-lived copy with
!  * active refcount=1.  Otherwise, only increment the refcount.
   */
  void
  PushActiveSnapshot(Snapshot snap)
--- 255,263 ----
   * PushActiveSnapshot
   *		Set the given snapshot as the current active snapshot
   *
!  * If the passed snapshot is a statically-allocated one, or it is possibly
!  * subject to a future command counter update, create a new long-lived copy
!  * with active refcount=1.  Otherwise, only increment the refcount.
   */
  void
  PushActiveSnapshot(Snapshot snap)
*************** PushActiveSnapshot(Snapshot snap)
*** 265,272 ****
  	Assert(snap != InvalidSnapshot);
  
  	newactive = MemoryContextAlloc(TopTransactionContext, sizeof(ActiveSnapshotElt));
! 	/* Static snapshot?  Create a persistent copy */
! 	newactive->as_snap = snap->copied ? snap : CopySnapshot(snap);
  	newactive->as_next = ActiveSnapshot;
  	newactive->as_level = GetCurrentTransactionNestLevel();
  
--- 267,282 ----
  	Assert(snap != InvalidSnapshot);
  
  	newactive = MemoryContextAlloc(TopTransactionContext, sizeof(ActiveSnapshotElt));
! 
! 	/*
! 	 * Checking SecondarySnapshot is probably useless here, but it seems better
! 	 * to be sure.
! 	 */
! 	if (snap == CurrentSnapshot || snap == SecondarySnapshot || !snap->copied)
! 		newactive->as_snap = CopySnapshot(snap);
! 	else
! 		newactive->as_snap = snap;
! 
  	newactive->as_next = ActiveSnapshot;
  	newactive->as_level = GetCurrentTransactionNestLevel();
  
Index: src/include/utils/snapmgr.h
===================================================================
RCS file: /home/alvherre/Code/cvs/pgsql/src/include/utils/snapmgr.h,v
retrieving revision 1.5.2.1
diff -c -p -r1.5.2.1 snapmgr.h
*** src/include/utils/snapmgr.h	2 Oct 2009 17:58:21 -0000	1.5.2.1
--- src/include/utils/snapmgr.h	6 Oct 2009 19:54:21 -0000
*************** extern TransactionId RecentGlobalXmin;
*** 26,32 ****
  extern Snapshot GetTransactionSnapshot(void);
  extern Snapshot GetLatestSnapshot(void);
  extern void SnapshotSetCommandId(CommandId curcid);
- extern Snapshot CopySnapshot(Snapshot snapshot);
  
  extern void PushActiveSnapshot(Snapshot snapshot);
  extern void PushUpdatedSnapshot(Snapshot snapshot);
--- 26,31 ----
Index: src/test/regress/expected/triggers.out
===================================================================
RCS file: /home/alvherre/Code/cvs/pgsql/src/test/regress/expected/triggers.out,v
retrieving revision 1.26
diff -c -p -r1.26 triggers.out
*** src/test/regress/expected/triggers.out	5 Nov 2008 18:49:28 -0000	1.26
--- src/test/regress/expected/triggers.out	6 Oct 2009 19:54:21 -0000
*************** NOTICE:  row 1 not changed
*** 537,542 ****
--- 537,573 ----
  NOTICE:  row 2 not changed
  DROP TABLE trigger_test;
  DROP FUNCTION mytrigger();
+ -- Test snapshot management in serializable transactions involving triggers
+ -- per bug report in 6bc73d4c0910042358k3d1adff3qa36f8df75198ecea@xxxxxxxxxxxxxx
+ CREATE FUNCTION serializable_update_trig() RETURNS trigger LANGUAGE plpgsql AS
+ $$
+ declare
+ 	rec record;
+ begin
+ 	new.description = 'updated in trigger';
+ 	return new;
+ end;
+ $$;
+ CREATE TABLE serializable_update_tab (
+ 	id int,
+ 	filler  text,
+ 	description text
+ );
+ CREATE TRIGGER serializable_update_trig BEFORE UPDATE ON serializable_update_tab
+ 	FOR EACH ROW EXECUTE PROCEDURE serializable_update_trig();
+ INSERT INTO serializable_update_tab SELECT a, repeat('xyzxz', 100), 'new'
+ 	FROM generate_series(1, 50) a;
+ BEGIN;
+ SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
+ UPDATE serializable_update_tab SET description = 'no no', id = 1 WHERE id = 1;
+ COMMIT;
+ SELECT description FROM serializable_update_tab WHERE id = 1;
+     description     
+ --------------------
+  updated in trigger
+ (1 row)
+ 
+ DROP TABLE serializable_update_tab;
  -- minimal update trigger
  CREATE TABLE min_updates_test (
  	f1	text,
Index: src/test/regress/sql/triggers.sql
===================================================================
RCS file: /home/alvherre/Code/cvs/pgsql/src/test/regress/sql/triggers.sql,v
retrieving revision 1.15
diff -c -p -r1.15 triggers.sql
*** src/test/regress/sql/triggers.sql	5 Nov 2008 18:49:28 -0000	1.15
--- src/test/regress/sql/triggers.sql	6 Oct 2009 19:54:21 -0000
*************** DROP TABLE trigger_test;
*** 416,421 ****
--- 416,451 ----
  
  DROP FUNCTION mytrigger();
  
+ -- Test snapshot management in serializable transactions involving triggers
+ -- per bug report in 6bc73d4c0910042358k3d1adff3qa36f8df75198ecea@xxxxxxxxxxxxxx
+ CREATE FUNCTION serializable_update_trig() RETURNS trigger LANGUAGE plpgsql AS
+ $$
+ declare
+ 	rec record;
+ begin
+ 	new.description = 'updated in trigger';
+ 	return new;
+ end;
+ $$;
+ 
+ CREATE TABLE serializable_update_tab (
+ 	id int,
+ 	filler  text,
+ 	description text
+ );
+ 
+ CREATE TRIGGER serializable_update_trig BEFORE UPDATE ON serializable_update_tab
+ 	FOR EACH ROW EXECUTE PROCEDURE serializable_update_trig();
+ 
+ INSERT INTO serializable_update_tab SELECT a, repeat('xyzxz', 100), 'new'
+ 	FROM generate_series(1, 50) a;
+ 
+ BEGIN;
+ SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
+ UPDATE serializable_update_tab SET description = 'no no', id = 1 WHERE id = 1;
+ COMMIT;
+ SELECT description FROM serializable_update_tab WHERE id = 1;
+ DROP TABLE serializable_update_tab;
  
  -- minimal update trigger
  
-- 
Sent via pgsql-general mailing list (pgsql-general@xxxxxxxxxxxxxx)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-general

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Postgresql Jobs]     [Postgresql Admin]     [Postgresql Performance]     [Linux Clusters]     [PHP Home]     [PHP on Windows]     [Kernel Newbies]     [PHP Classes]     [PHP Books]     [PHP Databases]     [Postgresql & PHP]     [Yosemite]
  Powered by Linux