Re: "could not open relation 1663/16384/16584: No such file or directory" in a specific combination of transactions with temp tables

Поиск
Список
Период
Сортировка
От Heikki Linnakangas
Тема Re: "could not open relation 1663/16384/16584: No such file or directory" in a specific combination of transactions with temp tables
Дата
Msg-id 47C8037F.7060906@enterprisedb.com
обсуждение исходный текст
Ответ на Re: "could not open relation 1663/16384/16584: No such file or directory" in a specific combination of transactions with temp tables  ("Heikki Linnakangas" <heikki@enterprisedb.com>)
Список pgsql-hackers
Heikki Linnakangas wrote:
> Attached is a simple patch to fix that by disallowing
> CREATE+DROP+PREPARE TRANSACTION more reliably.

That patch was missing changes to header files. New patch attached.

--
   Heikki Linnakangas
   EnterpriseDB   http://www.enterprisedb.com
Index: src/backend/access/transam/twophase.c
===================================================================
RCS file: /home/hlinnaka/pgcvsrepository/pgsql/src/backend/access/transam/twophase.c,v
retrieving revision 1.39
diff -c -r1.39 twophase.c
*** src/backend/access/transam/twophase.c    1 Jan 2008 19:45:48 -0000    1.39
--- src/backend/access/transam/twophase.c    29 Feb 2008 13:05:24 -0000
***************
*** 793,798 ****
--- 793,799 ----
      TransactionId *children;
      RelFileNode *commitrels;
      RelFileNode *abortrels;
+     bool haveTempCommit, haveTempAbort;

      /* Initialize linked list */
      records.head = palloc0(sizeof(XLogRecData));
***************
*** 815,824 ****
      hdr.prepared_at = gxact->prepared_at;
      hdr.owner = gxact->owner;
      hdr.nsubxacts = xactGetCommittedChildren(&children);
!     hdr.ncommitrels = smgrGetPendingDeletes(true, &commitrels, NULL);
!     hdr.nabortrels = smgrGetPendingDeletes(false, &abortrels, NULL);
      StrNCpy(hdr.gid, gxact->gid, GIDSIZE);

      save_state_data(&hdr, sizeof(TwoPhaseFileHeader));

      /* Add the additional info about subxacts and deletable files */
--- 816,830 ----
      hdr.prepared_at = gxact->prepared_at;
      hdr.owner = gxact->owner;
      hdr.nsubxacts = xactGetCommittedChildren(&children);
!     hdr.ncommitrels = smgrGetPendingDeletes(true, &commitrels, NULL, &haveTempCommit);
!     hdr.nabortrels = smgrGetPendingDeletes(false, &abortrels, NULL, &haveTempAbort);
      StrNCpy(hdr.gid, gxact->gid, GIDSIZE);

+     if (haveTempCommit || haveTempAbort)
+         ereport(ERROR,
+                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+                  errmsg("cannot PREPARE a transaction that has operated on temporary tables")));
+
      save_state_data(&hdr, sizeof(TwoPhaseFileHeader));

      /* Add the additional info about subxacts and deletable files */
Index: src/backend/access/transam/xact.c
===================================================================
RCS file: /home/hlinnaka/pgcvsrepository/pgsql/src/backend/access/transam/xact.c,v
retrieving revision 1.257
diff -c -r1.257 xact.c
*** src/backend/access/transam/xact.c    15 Jan 2008 18:56:59 -0000    1.257
--- src/backend/access/transam/xact.c    29 Feb 2008 13:05:24 -0000
***************
*** 802,808 ****
      TransactionId *children;

      /* Get data needed for commit record */
!     nrels = smgrGetPendingDeletes(true, &rels, &haveNonTemp);
      nchildren = xactGetCommittedChildren(&children);

      /*
--- 802,808 ----
      TransactionId *children;

      /* Get data needed for commit record */
!     nrels = smgrGetPendingDeletes(true, &rels, &haveNonTemp, NULL);
      nchildren = xactGetCommittedChildren(&children);

      /*
***************
*** 1174,1180 ****
               xid);

      /* Fetch the data we need for the abort record */
!     nrels = smgrGetPendingDeletes(false, &rels, NULL);
      nchildren = xactGetCommittedChildren(&children);

      /* XXX do we really need a critical section here? */
--- 1174,1180 ----
               xid);

      /* Fetch the data we need for the abort record */
!     nrels = smgrGetPendingDeletes(false, &rels, NULL, NULL);
      nchildren = xactGetCommittedChildren(&children);

      /* XXX do we really need a critical section here? */
Index: src/backend/storage/smgr/smgr.c
===================================================================
RCS file: /home/hlinnaka/pgcvsrepository/pgsql/src/backend/storage/smgr/smgr.c,v
retrieving revision 1.109
diff -c -r1.109 smgr.c
*** src/backend/storage/smgr/smgr.c    1 Jan 2008 19:45:52 -0000    1.109
--- src/backend/storage/smgr/smgr.c    29 Feb 2008 13:05:24 -0000
***************
*** 678,689 ****
   *
   * If haveNonTemp isn't NULL, the bool it points to gets set to true if
   * there is any non-temp table pending to be deleted; false if not.
   *
   * Note that the list does not include anything scheduled for termination
   * by upper-level transactions.
   */
  int
! smgrGetPendingDeletes(bool forCommit, RelFileNode **ptr, bool *haveNonTemp)
  {
      int            nestLevel = GetCurrentTransactionNestLevel();
      int            nrels;
--- 678,692 ----
   *
   * If haveNonTemp isn't NULL, the bool it points to gets set to true if
   * there is any non-temp table pending to be deleted; false if not.
+  * haveTemp is similar, but gets set if there is any temp table deletions
+  * pending.
   *
   * Note that the list does not include anything scheduled for termination
   * by upper-level transactions.
   */
  int
! smgrGetPendingDeletes(bool forCommit, RelFileNode **ptr,
!                       bool *haveNonTemp, bool *haveTemp)
  {
      int            nestLevel = GetCurrentTransactionNestLevel();
      int            nrels;
***************
*** 693,698 ****
--- 696,703 ----
      nrels = 0;
      if (haveNonTemp)
          *haveNonTemp = false;
+     if (haveTemp)
+         *haveTemp = false;
      for (pending = pendingDeletes; pending != NULL; pending = pending->next)
      {
          if (pending->nestLevel >= nestLevel && pending->atCommit == forCommit)
***************
*** 711,716 ****
--- 716,723 ----
              *rptr++ = pending->relnode;
          if (haveNonTemp && !pending->isTemp)
              *haveNonTemp = true;
+         if (haveTemp && pending->isTemp)
+             *haveTemp = true;
      }
      return nrels;
  }
Index: src/include/storage/smgr.h
===================================================================
RCS file: /home/hlinnaka/pgcvsrepository/pgsql/src/include/storage/smgr.h,v
retrieving revision 1.62
diff -c -r1.62 smgr.h
*** src/include/storage/smgr.h    1 Jan 2008 19:45:59 -0000    1.62
--- src/include/storage/smgr.h    29 Feb 2008 09:47:24 -0000
***************
*** 77,83 ****
  extern void smgrimmedsync(SMgrRelation reln);
  extern void smgrDoPendingDeletes(bool isCommit);
  extern int smgrGetPendingDeletes(bool forCommit, RelFileNode **ptr,
!                       bool *haveNonTemp);
  extern void AtSubCommit_smgr(void);
  extern void AtSubAbort_smgr(void);
  extern void PostPrepare_smgr(void);
--- 77,83 ----
  extern void smgrimmedsync(SMgrRelation reln);
  extern void smgrDoPendingDeletes(bool isCommit);
  extern int smgrGetPendingDeletes(bool forCommit, RelFileNode **ptr,
!                       bool *haveNonTemp, bool *haveTemp);
  extern void AtSubCommit_smgr(void);
  extern void AtSubAbort_smgr(void);
  extern void PostPrepare_smgr(void);

В списке pgsql-hackers по дате отправления:

Предыдущее
От: "Pavan Deolasee"
Дата:
Сообщение: Read-ahead and parallelism in redo recovery
Следующее
От: "Gurjeet Singh"
Дата:
Сообщение: Re: "could not open relation 1663/16384/16584: No such file or directory" in a specific combination of transactions with temp tables