http://archives.postgresql.org/pgsql-hackers/2006-10/msg01172.php
As discussed on -hackers, its possible to avoid writing any WAL at all for COPY in these circumstances: BEGIN; CREATE TABLE foo.. COPY foo... COMMIT; BEGIN; TRUNCATE foo.. COPY foo... COMMIT; The enclosed patch implements this, as discussed. There is no user interface to enable/disable, just as with CTAS and CREATE INDEX; no docs, just code comments. This plays nicely with the --single-transaction option in psql to allow fast restores/upgrades. YMMV but disk bound COPY will benefit greatly from this patch, some tests showing 100% gain. COPY is still *very* CPU intensive, so some tests have shown negligible benefit, fyi, but that isn't the typical case. Applies cleanly to CVS HEAD, passes make check. -- Simon Riggs EnterpriseDB http://www.enterprisedb.com
Index: src/backend/access/heap/heapam.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/access/heap/heapam.c,v retrieving revision 1.222 diff -c -r1.222 heapam.c *** src/backend/access/heap/heapam.c 17 Nov 2006 18:00:14 -0000 1.222 --- src/backend/access/heap/heapam.c 4 Jan 2007 15:24:03 -0000 *************** *** 28,33 **** --- 28,34 ---- * heap_update - replace a tuple in a relation with another tuple * heap_markpos - mark scan position * heap_restrpos - restore position to marked location + * heap_sync - sync heap, for when no WAL has been written * * NOTES * This file contains the heap_ routines which implement *************** *** 50,55 **** --- 51,57 ---- #include "miscadmin.h" #include "pgstat.h" #include "storage/procarray.h" + #include "storage/smgr.h" #include "utils/inval.h" #include "utils/lsyscache.h" #include "utils/relcache.h" *************** *** 1357,1364 **** * non-temp relation. Safe usage of this behavior requires that we arrange * that all new tuples go into new pages not containing any tuples from other * transactions, that the relation gets fsync'd before commit, and that the ! * transaction emits at least one WAL record to ensure RecordTransactionCommit ! * will decide to WAL-log the commit. * * use_fsm is passed directly to RelationGetBufferForTuple, which see for * more info. --- 1359,1367 ---- * non-temp relation. Safe usage of this behavior requires that we arrange * that all new tuples go into new pages not containing any tuples from other * transactions, that the relation gets fsync'd before commit, and that the ! * transaction emits at least one WAL record or must mark ! * MyXactMadeXLogEntry=true to ensure RecordTransactionCommit will ! * decide to WAL-log the commit. (see heap_sync() comments also) * * use_fsm is passed directly to RelationGetBufferForTuple, which see for * more info. *************** *** 1371,1377 **** */ Oid heap_insert(Relation relation, HeapTuple tup, CommandId cid, ! bool use_wal, bool use_fsm) { TransactionId xid = GetCurrentTransactionId(); HeapTuple heaptup; --- 1374,1380 ---- */ Oid heap_insert(Relation relation, HeapTuple tup, CommandId cid, ! bool use_wal, bool use_fsm, bool force_committed) { TransactionId xid = GetCurrentTransactionId(); HeapTuple heaptup; *************** *** 1408,1413 **** --- 1411,1419 ---- HeapTupleHeaderSetXmax(tup->t_data, 0); /* zero out Datum fields */ HeapTupleHeaderSetCmax(tup->t_data, 0); /* for cleanliness */ tup->t_tableOid = RelationGetRelid(relation); + if (force_committed) + tup->t_data->t_infomask |= HEAP_XMIN_COMMITTED; + /* * If the new tuple is too big for storage or contains already toasted *************** *** 1418,1424 **** */ if (HeapTupleHasExternal(tup) || (MAXALIGN(tup->t_len) > TOAST_TUPLE_THRESHOLD)) ! heaptup = toast_insert_or_update(relation, tup, NULL); else heaptup = tup; --- 1424,1430 ---- */ if (HeapTupleHasExternal(tup) || (MAXALIGN(tup->t_len) > TOAST_TUPLE_THRESHOLD)) ! heaptup = toast_insert_or_update(relation, tup, NULL, use_wal); else heaptup = tup; *************** *** 1532,1538 **** Oid simple_heap_insert(Relation relation, HeapTuple tup) { ! return heap_insert(relation, tup, GetCurrentCommandId(), true, true); } /* --- 1538,1556 ---- Oid simple_heap_insert(Relation relation, HeapTuple tup) { ! return heap_insert(relation, tup, GetCurrentCommandId(), true, true, false); ! } ! ! /* ! * fast_heap_insert - insert a tuple with options to improve speed ! * ! * Currently, this routine allows specifying additional options for speed ! * in certain cases, such as WAL-avoiding COPY command ! */ ! Oid ! fast_heap_insert(Relation relation, HeapTuple tup, bool use_wal, bool force_committed) ! { ! return heap_insert(relation, tup, GetCurrentCommandId(), use_wal, use_wal, force_committed); } /* *************** *** 2086,2096 **** * * Note: below this point, heaptup is the data we actually intend to * store into the relation; newtup is the caller's original untoasted ! * data. */ if (need_toast) { ! heaptup = toast_insert_or_update(relation, newtup, &oldtup); newtupsize = MAXALIGN(heaptup->t_len); } else --- 2104,2114 ---- * * Note: below this point, heaptup is the data we actually intend to * store into the relation; newtup is the caller's original untoasted ! * data. (We always use WAL for toast table updates.) */ if (need_toast) { ! heaptup = toast_insert_or_update(relation, newtup, &oldtup, true); newtupsize = MAXALIGN(heaptup->t_len); } else *************** *** 3966,3968 **** --- 3984,4007 ---- else appendStringInfo(buf, "UNKNOWN"); } + + /* ---------------- + * heap_sync - sync a heap, for use when no WAL has been written + * + * ---------------- + */ + void + heap_sync(Relation rel) + { + if (!rel->rd_istemp) + { + /* + * If we skipped using WAL, and it's not a temp relation, + * we must force the relation down to disk before it's + * safe to commit the transaction. This requires forcing + * out any dirty buffers and then doing a forced fsync. + */ + FlushRelationBuffers(rel); + smgrimmedsync(rel->rd_smgr); + } + } Index: src/backend/access/heap/tuptoaster.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/access/heap/tuptoaster.c,v retrieving revision 1.66 diff -c -r1.66 tuptoaster.c *** src/backend/access/heap/tuptoaster.c 5 Oct 2006 23:33:33 -0000 1.66 --- src/backend/access/heap/tuptoaster.c 4 Jan 2007 15:24:04 -0000 *************** *** 42,48 **** #undef TOAST_DEBUG static void toast_delete_datum(Relation rel, Datum value); ! static Datum toast_save_datum(Relation rel, Datum value); static varattrib *toast_fetch_datum(varattrib *attr); static varattrib *toast_fetch_datum_slice(varattrib *attr, int32 sliceoffset, int32 length); --- 42,48 ---- #undef TOAST_DEBUG static void toast_delete_datum(Relation rel, Datum value); ! static Datum toast_save_datum(Relation rel, Datum value, bool use_wal); static varattrib *toast_fetch_datum(varattrib *attr); static varattrib *toast_fetch_datum_slice(varattrib *attr, int32 sliceoffset, int32 length); *************** *** 342,348 **** * ---------- */ HeapTuple ! toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup) { HeapTuple result_tuple; TupleDesc tupleDesc; --- 342,348 ---- * ---------- */ HeapTuple ! toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup, bool use_wal) { HeapTuple result_tuple; TupleDesc tupleDesc; *************** *** 612,618 **** i = biggest_attno; old_value = toast_values[i]; toast_action[i] = 'p'; ! toast_values[i] = toast_save_datum(rel, toast_values[i]); if (toast_free[i]) pfree(DatumGetPointer(old_value)); --- 612,618 ---- i = biggest_attno; old_value = toast_values[i]; toast_action[i] = 'p'; ! toast_values[i] = toast_save_datum(rel, toast_values[i], use_wal); if (toast_free[i]) pfree(DatumGetPointer(old_value)); *************** *** 724,730 **** i = biggest_attno; old_value = toast_values[i]; toast_action[i] = 'p'; ! toast_values[i] = toast_save_datum(rel, toast_values[i]); if (toast_free[i]) pfree(DatumGetPointer(old_value)); --- 724,730 ---- i = biggest_attno; old_value = toast_values[i]; toast_action[i] = 'p'; ! toast_values[i] = toast_save_datum(rel, toast_values[i], use_wal); if (toast_free[i]) pfree(DatumGetPointer(old_value)); *************** *** 972,978 **** * ---------- */ static Datum ! toast_save_datum(Relation rel, Datum value) { Relation toastrel; Relation toastidx; --- 972,978 ---- * ---------- */ static Datum ! toast_save_datum(Relation rel, Datum value, bool use_wal) { Relation toastrel; Relation toastidx; *************** *** 1057,1063 **** if (!HeapTupleIsValid(toasttup)) elog(ERROR, "failed to build TOAST tuple"); ! simple_heap_insert(toastrel, toasttup); /* * Create the index entry. We cheat a little here by not using --- 1057,1064 ---- if (!HeapTupleIsValid(toasttup)) elog(ERROR, "failed to build TOAST tuple"); ! /* not worried about forcing commit bits to be set for TOAST */ ! fast_heap_insert(toastrel, toasttup, use_wal, !use_wal); /* * Create the index entry. We cheat a little here by not using Index: src/backend/catalog/index.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/catalog/index.c,v retrieving revision 1.274 diff -c -r1.274 index.c *** src/backend/catalog/index.c 4 Oct 2006 00:29:50 -0000 1.274 --- src/backend/catalog/index.c 4 Jan 2007 15:24:06 -0000 *************** *** 1238,1243 **** --- 1238,1246 ---- heap_close(pg_class, RowExclusiveLock); + /* Remember we did this in current transaction, to allow later optimisations */ + relation->rd_newRelfilenodeSubid = GetCurrentSubTransactionId(); + /* Make sure the relfilenode change is visible */ CommandCounterIncrement(); } Index: src/backend/commands/copy.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/commands/copy.c,v retrieving revision 1.273 diff -c -r1.273 copy.c *** src/backend/commands/copy.c 6 Oct 2006 17:13:58 -0000 1.273 --- src/backend/commands/copy.c 4 Jan 2007 15:24:08 -0000 *************** *** 1652,1657 **** --- 1652,1659 ---- ExprContext *econtext; /* used for ExecEvalExpr for default atts */ MemoryContext oldcontext = CurrentMemoryContext; ErrorContextCallback errcontext; + bool use_wal = true; /* By default, we use WAL to log db changes */ + bool force_committed = false; Assert(cstate->rel); *************** *** 1843,1848 **** --- 1845,1878 ---- nfields = file_has_oids ? (attr_count + 1) : attr_count; field_strings = (char **) palloc(nfields * sizeof(char *)); + /* + * Check for performance optimization by avoiding WAL writes + * + * If archive logging is not be enabled *and* either + * - table is created in same transaction as this COPY + * - table data is now being written to new relfilenode + * then we can safely avoid writing WAL. Why? + * The data files for the table plus toast table/index, plus any indexes + * will all be dropped at the end of the transaction if it fails, so we + * do not need to worry about inconsistent states. + * As mentioned in comments in utils/rel.h, the in-same-transaction test is + * not completely reliable, since rd_createSubId can be reset to zero in + * certain cases before the end of the creating transaction. + * We are doing this for performance only, so we only need to know: + * if rd_createSubid != InvalidSubTransactionId then it is *always* just + * created. + * We also want to set HEAP_XMIN_COMMITTED for these tuples, so we + * can only do this when we don't have a previously open portal. + * COPY itself open a portal, so we check for just a single portal. + * If we have PITR enabled, then we must use_wal + */ + if (NumAccessiblePortals() == 1 && + (cstate->rel->rd_createSubid != InvalidSubTransactionId || + cstate->rel->rd_newRelfilenodeSubid != InvalidSubTransactionId)) + force_committed = true; + if (force_committed && !XLogArchivingActive()) + use_wal = false; + /* Initialize state variables */ cstate->fe_eof = false; cstate->eol_type = EOL_UNKNOWN; *************** *** 2076,2082 **** ExecConstraints(resultRelInfo, slot, estate); /* OK, store the tuple and create index entries for it */ ! simple_heap_insert(cstate->rel, tuple); if (resultRelInfo->ri_NumIndices > 0) ExecInsertIndexTuples(slot, &(tuple->t_self), estate, false); --- 2106,2112 ---- ExecConstraints(resultRelInfo, slot, estate); /* OK, store the tuple and create index entries for it */ ! fast_heap_insert(cstate->rel, tuple, use_wal, force_committed); if (resultRelInfo->ri_NumIndices > 0) ExecInsertIndexTuples(slot, &(tuple->t_self), estate, false); *************** *** 2093,2098 **** --- 2123,2154 ---- } } + /* + * If we skipped writing WAL for heaps, then we need to sync + */ + if (!use_wal) + { + /* main heap */ + heap_sync(cstate->rel); + + /* main heap indexes, if any */ + /* we always use WAL for index inserts, so no need to sync */ + + /* toast heap, if any */ + if (OidIsValid(cstate->rel->rd_rel->reltoastrelid)) + { + Relation toastrel; + + toastrel = heap_open(cstate->rel->rd_rel->reltoastrelid, + AccessShareLock); + heap_sync(toastrel); + heap_close(toastrel, AccessShareLock); + } + + /* toast index, if toast heap */ + /* we always use WAL for index inserts, so no need to sync */ + } + /* Done, clean up */ error_context_stack = errcontext.previous; Index: src/backend/executor/execMain.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/executor/execMain.c,v retrieving revision 1.282 diff -c -r1.282 execMain.c *** src/backend/executor/execMain.c 26 Dec 2006 21:37:19 -0000 1.282 --- src/backend/executor/execMain.c 4 Jan 2007 15:24:08 -0000 *************** *** 1410,1416 **** */ newId = heap_insert(resultRelationDesc, tuple, estate->es_snapshot->curcid, ! true, true); IncrAppended(); (estate->es_processed)++; --- 1410,1416 ---- */ newId = heap_insert(resultRelationDesc, tuple, estate->es_snapshot->curcid, ! true, true, false); IncrAppended(); (estate->es_processed)++; *************** *** 2516,2526 **** */ if (!estate->es_into_relation_use_wal && !estate->es_into_relation_descriptor->rd_istemp) ! { ! FlushRelationBuffers(estate->es_into_relation_descriptor); ! /* FlushRelationBuffers will have opened rd_smgr */ ! smgrimmedsync(estate->es_into_relation_descriptor->rd_smgr); ! } /* close rel, but keep lock until commit */ heap_close(estate->es_into_relation_descriptor, NoLock); --- 2516,2522 ---- */ if (!estate->es_into_relation_use_wal && !estate->es_into_relation_descriptor->rd_istemp) ! heap_sync(estate->es_into_relation_descriptor); /* close rel, but keep lock until commit */ heap_close(estate->es_into_relation_descriptor, NoLock); *************** *** 2577,2583 **** tuple, estate->es_snapshot->curcid, estate->es_into_relation_use_wal, ! false); /* never any point in using FSM */ /* We know this is a newly created relation, so there are no indexes */ --- 2573,2580 ---- tuple, estate->es_snapshot->curcid, estate->es_into_relation_use_wal, ! false, /* never any point in using FSM */ ! true); /* We know this is a newly created relation, so there are no indexes */ Index: src/backend/utils/cache/relcache.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/utils/cache/relcache.c,v retrieving revision 1.252 diff -c -r1.252 relcache.c *** src/backend/utils/cache/relcache.c 31 Dec 2006 20:32:04 -0000 1.252 --- src/backend/utils/cache/relcache.c 4 Jan 2007 15:24:10 -0000 *************** *** 836,841 **** --- 836,842 ---- relation->rd_refcnt = 0; relation->rd_isnailed = false; relation->rd_createSubid = InvalidSubTransactionId; + relation->rd_newRelfilenodeSubid = InvalidSubTransactionId; relation->rd_istemp = isTempNamespace(relation->rd_rel->relnamespace); /* *************** *** 1342,1347 **** --- 1343,1349 ---- */ relation->rd_isnailed = true; relation->rd_createSubid = InvalidSubTransactionId; + relation->rd_newRelfilenodeSubid = InvalidSubTransactionId; relation->rd_istemp = false; /* *************** *** 1753,1758 **** --- 1755,1761 ---- Oid save_relid = RelationGetRelid(relation); int old_refcnt = relation->rd_refcnt; SubTransactionId old_createSubid = relation->rd_createSubid; + SubTransactionId old_newRelfilenodeSubid = relation->rd_newRelfilenodeSubid; TupleDesc old_att = relation->rd_att; RuleLock *old_rules = relation->rd_rules; MemoryContext old_rulescxt = relation->rd_rulescxt; *************** *** 1771,1776 **** --- 1774,1781 ---- } relation->rd_refcnt = old_refcnt; relation->rd_createSubid = old_createSubid; + relation->rd_newRelfilenodeSubid = old_newRelfilenodeSubid; + if (equalTupleDescs(old_att, relation->rd_att)) { /* needn't flush typcache here */ *************** *** 1811,1817 **** { bool rebuild; ! if (relation->rd_createSubid != InvalidSubTransactionId) { /* * New relcache entries are always rebuilt, not flushed; else we'd --- 1816,1823 ---- { bool rebuild; ! if (relation->rd_createSubid != InvalidSubTransactionId || ! relation->rd_newRelfilenodeSubid != InvalidSubTransactionId) { /* * New relcache entries are always rebuilt, not flushed; else we'd *************** *** 1893,1898 **** --- 1899,1907 ---- * so we do not touch new-in-transaction relations; they cannot be targets * of cross-backend SI updates (and our own updates now go through a * separate linked list that isn't limited by the SI message buffer size). + * We don't do anything special for newRelfilenode-in-transaction relations, + * though since we have a lock on the relation nobody else should be + * generating cache invalidation messages for it anyhow. * * We do this in two phases: the first pass deletes deletable items, and * the second one rebuilds the rebuildable items. This is essential for *************** *** 2069,2074 **** --- 2078,2084 ---- continue; } } + relation->rd_newRelfilenodeSubid = InvalidSubTransactionId; /* * Flush any temporary index list. *************** *** 2130,2135 **** --- 2140,2152 ---- continue; } } + if (relation->rd_newRelfilenodeSubid == mySubid) + { + if (isCommit) + relation->rd_newRelfilenodeSubid = parentSubid; + else + relation->rd_newRelfilenodeSubid = InvalidSubTransactionId; + } /* * Flush any temporary index list. *************** *** 2219,2224 **** --- 2236,2242 ---- /* it's being created in this transaction */ rel->rd_createSubid = GetCurrentSubTransactionId(); + rel->rd_newRelfilenodeSubid = InvalidSubTransactionId; /* must flag that we have rels created in this transaction */ need_eoxact_work = true; *************** *** 3364,3369 **** --- 3382,3388 ---- rel->rd_indexlist = NIL; rel->rd_oidindex = InvalidOid; rel->rd_createSubid = InvalidSubTransactionId; + rel->rd_newRelfilenodeSubid = InvalidSubTransactionId; rel->rd_amcache = NULL; MemSet(&rel->pgstat_info, 0, sizeof(rel->pgstat_info)); Index: src/backend/utils/mmgr/portalmem.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/utils/mmgr/portalmem.c,v retrieving revision 1.97 diff -c -r1.97 portalmem.c *** src/backend/utils/mmgr/portalmem.c 23 Nov 2006 01:14:59 -0000 1.97 --- src/backend/utils/mmgr/portalmem.c 4 Jan 2007 15:24:12 -0000 *************** *** 88,94 **** } while(0) static MemoryContext PortalMemory = NULL; ! /* ---------------------------------------------------------------- * public portal interface functions --- 88,94 ---- } while(0) static MemoryContext PortalMemory = NULL; ! static int NPortals = 0; /* ---------------------------------------------------------------- * public portal interface functions *************** *** 227,232 **** --- 227,234 ---- /* put portal in table (sets portal->name) */ PortalHashTableInsert(portal, name); + ++NPortals; + return portal; } *************** *** 410,415 **** --- 412,420 ---- /* release portal struct (it's in PortalMemory) */ pfree(portal); + + if (--NPortals < 0) + elog(ERROR, "error in number of portals"); } /* *************** *** 548,554 **** HASH_SEQ_STATUS status; PortalHashEnt *hentry; ! hash_seq_init(&status, PortalHashTable); while ((hentry = (PortalHashEnt *) hash_seq_search(&status)) != NULL) { --- 553,559 ---- HASH_SEQ_STATUS status; PortalHashEnt *hentry; ! hash_seq_init(&status, PortalHashTable); while ((hentry = (PortalHashEnt *) hash_seq_search(&status)) != NULL) { *************** *** 802,807 **** --- 807,823 ---- } } + /* + * Get the number of portals from which the backend *could* retrieve + * tuples. This is an important number for the safe use of some + * performance optimizations. + */ + int + NumAccessiblePortals(void) + { + return NPortals; + } + /* Find all available cursors */ Datum pg_cursor(PG_FUNCTION_ARGS) Index: src/include/miscadmin.h =================================================================== RCS file: /projects/cvsroot/pgsql/src/include/miscadmin.h,v retrieving revision 1.190 diff -c -r1.190 miscadmin.h *** src/include/miscadmin.h 19 Oct 2006 18:32:47 -0000 1.190 --- src/include/miscadmin.h 4 Jan 2007 15:24:13 -0000 *************** *** 216,221 **** --- 216,224 ---- /* in tcop/postgres.c */ extern void check_stack_depth(void); + /* in utils/mmgr/portalmem.c */ + extern int NumAccessiblePortals(void); + /***************************************************************************** * pdir.h -- * Index: src/include/access/heapam.h =================================================================== RCS file: /projects/cvsroot/pgsql/src/include/access/heapam.h,v retrieving revision 1.117 diff -c -r1.117 heapam.h *** src/include/access/heapam.h 5 Nov 2006 22:42:10 -0000 1.117 --- src/include/access/heapam.h 4 Jan 2007 15:24:13 -0000 *************** *** 157,163 **** extern void setLastTid(const ItemPointer tid); extern Oid heap_insert(Relation relation, HeapTuple tup, CommandId cid, ! bool use_wal, bool use_fsm); extern HTSU_Result heap_delete(Relation relation, ItemPointer tid, ItemPointer ctid, TransactionId *update_xmax, CommandId cid, Snapshot crosscheck, bool wait); --- 157,163 ---- extern void setLastTid(const ItemPointer tid); extern Oid heap_insert(Relation relation, HeapTuple tup, CommandId cid, ! bool use_wal, bool use_fsm, bool force_committed); extern HTSU_Result heap_delete(Relation relation, ItemPointer tid, ItemPointer ctid, TransactionId *update_xmax, CommandId cid, Snapshot crosscheck, bool wait); *************** *** 178,183 **** --- 178,186 ---- extern void simple_heap_update(Relation relation, ItemPointer otid, HeapTuple tup); + extern Oid fast_heap_insert(Relation relation, HeapTuple tup, bool use_wal, + bool force_committed); + extern void heap_markpos(HeapScanDesc scan); extern void heap_restrpos(HeapScanDesc scan); *************** *** 236,239 **** --- 239,244 ---- extern HeapTuple heap_addheader(int natts, bool withoid, Size structlen, void *structure); + extern void heap_sync(Relation relation); + #endif /* HEAPAM_H */ Index: src/include/access/tuptoaster.h =================================================================== RCS file: /projects/cvsroot/pgsql/src/include/access/tuptoaster.h,v retrieving revision 1.28 diff -c -r1.28 tuptoaster.h *** src/include/access/tuptoaster.h 13 Jul 2006 17:47:01 -0000 1.28 --- src/include/access/tuptoaster.h 4 Jan 2007 15:24:13 -0000 *************** *** 69,75 **** * ---------- */ extern HeapTuple toast_insert_or_update(Relation rel, ! HeapTuple newtup, HeapTuple oldtup); /* ---------- * toast_delete - --- 69,75 ---- * ---------- */ extern HeapTuple toast_insert_or_update(Relation rel, ! HeapTuple newtup, HeapTuple oldtup, bool use_wal); /* ---------- * toast_delete - Index: src/include/utils/rel.h =================================================================== RCS file: /projects/cvsroot/pgsql/src/include/utils/rel.h,v retrieving revision 1.93 diff -c -r1.93 rel.h *** src/include/utils/rel.h 23 Dec 2006 00:43:13 -0000 1.93 --- src/include/utils/rel.h 4 Jan 2007 15:24:13 -0000 *************** *** 137,142 **** --- 137,144 ---- char rd_indexvalid; /* state of rd_indexlist: 0 = not valid, 1 = * valid, 2 = temporarily forced */ SubTransactionId rd_createSubid; /* rel was created in current xact */ + SubTransactionId rd_newRelfilenodeSubid; /* rel had new relfilenode in current xact */ + /* * rd_createSubid is the ID of the highest subtransaction the rel has
---------------------------(end of broadcast)--------------------------- TIP 5: don't forget to increase your free space map settings