Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 0 additions & 27 deletions src/backend/access/aocs/aocsam.c
Original file line number Diff line number Diff line change
Expand Up @@ -409,29 +409,6 @@ open_next_scan_seg(AOCSScanDesc scan)
*/
if (scan->blockDirectory)
{
/*
* if building the block directory, we need to make sure
* the sequence starts higher than our highest tuple's
* rownum. In the case of upgraded blocks, the highest
* tuple will have tupCount as its row num for non-upgrade
* cases, which use the sequence, it will be enough to
* start off the end of the sequence; note that this is
* not ideal -- if we are at least curSegInfo->tupcount +
* 1 then we don't even need to update the sequence value
*/
int64 firstSequence;
Oid segrelid;
GetAppendOnlyEntryAuxOids(RelationGetRelid(scan->rs_base.rs_rd),
scan->appendOnlyMetaDataSnapshot,
&segrelid, NULL, NULL,
NULL, NULL);

firstSequence =
GetFastSequences(segrelid,
curSegInfo->segno,
curSegInfo->total_tupcount + 1,
NUM_FAST_SEQUENCES);

AppendOnlyBlockDirectory_Init_forInsert(scan->blockDirectory,
scan->appendOnlyMetaDataSnapshot,
(FileSegInfo *) curSegInfo,
Expand All @@ -440,10 +417,6 @@ open_next_scan_seg(AOCSScanDesc scan)
curSegInfo->segno,
scan->columnScanInfo.relationTupleDesc->natts,
true);

InsertFastSequenceEntry(segrelid,
curSegInfo->segno,
firstSequence);
}

open_all_datumstreamread_segfiles(scan->rs_base.rs_rd,
Expand Down
4 changes: 0 additions & 4 deletions src/backend/access/aocs/aocssegfiles.c
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,6 @@ InsertInitialAOCSFileSegInfo(Relation prel, int32 segno, int32 nvp, Oid segrelid

segrel = heap_open(segrelid, RowExclusiveLock);

InsertFastSequenceEntry(segrelid,
(int64) segno,
0);

values[Anum_pg_aocs_segno - 1] = Int32GetDatum(segno);
values[Anum_pg_aocs_vpinfo - 1] = PointerGetDatum(vpinfo);
values[Anum_pg_aocs_tupcount - 1] = Int64GetDatum(0);
Expand Down
4 changes: 0 additions & 4 deletions src/backend/access/appendonly/aosegfiles.c
Original file line number Diff line number Diff line change
Expand Up @@ -110,10 +110,6 @@ InsertInitialSegnoEntry(Relation parentrel, int segno)

GetAppendOnlyEntryAuxOids(parentrel->rd_id, NULL, &segrelid, NULL, NULL, NULL, NULL);

InsertFastSequenceEntry(segrelid,
(int64) segno,
0);

pg_aoseg_rel = heap_open(segrelid, RowExclusiveLock);

pg_aoseg_dsc = RelationGetDescr(pg_aoseg_rel);
Expand Down
25 changes: 0 additions & 25 deletions src/backend/access/appendonly/appendonlyam.c
Original file line number Diff line number Diff line change
Expand Up @@ -305,27 +305,6 @@ SetNextFileSegForRead(AppendOnlyScanDesc scan)
/* Initialize the block directory for inserts if needed. */
if (scan->blockDirectory)
{
Oid segrelid;

GetAppendOnlyEntryAuxOids(reln->rd_id, NULL,
&segrelid, NULL, NULL, NULL, NULL);

/*
* if building the block directory, we need to make sure the
* sequence starts higher than our highest tuple's rownum. In
* the case of upgraded blocks, the highest tuple will have
* tupCount as its row num for non-upgrade cases, which use
* the sequence, it will be enough to start off the end of the
* sequence; note that this is not ideal -- if we are at least
* curSegInfo->tupcount + 1 then we don't even need to update
* the sequence value.
*/
int64 firstSequence =
GetFastSequences(segrelid,
segno,
fsinfo->total_tupcount + 1,
NUM_FAST_SEQUENCES);

AppendOnlyBlockDirectory_Init_forInsert(scan->blockDirectory,
scan->appendOnlyMetaDataSnapshot,
fsinfo,
Expand All @@ -334,10 +313,6 @@ SetNextFileSegForRead(AppendOnlyScanDesc scan)
segno, /* segno */
1, /* columnGroupNo */
false);

InsertFastSequenceEntry(segrelid,
segno,
firstSequence);
}

finished_all_files = false;
Expand Down
63 changes: 62 additions & 1 deletion src/backend/access/heap/heapam.c
Original file line number Diff line number Diff line change
Expand Up @@ -6876,6 +6876,64 @@ heap_freeze_tuple(HeapTupleHeader tuple,
return do_freeze;
}

/*
* GPDB: heap_freeze_tuple_wal_logged
* Similar to heap_freeze_tuple, but with WAL logging AND do not check
* cutoff xid (i.e. we blindly freeze a tuple and write WAL for it).
*
* Useful when we want to freeze a tuple immediately after inserting it.
*/
void
heap_freeze_tuple_wal_logged(Relation rel, HeapTuple tup)
{
xl_heap_freeze_tuple frozen = {0};
Buffer buffer;
Page page;
HeapTupleHeader htup;

/* Set the passed-in tuple to be frozen */
HeapTupleHeaderSetXminFrozen(tup->t_data);

/*
* Prepare the xl_heap_freeze_tuple manually (instead of heap_prepare_freeze_tuple)
* as we do not need the checks in heap_prepare_freeze_tuple. Note that this would
* suffer from having more field been added to xl_heap_freeze_tuple in future.
* But that would be caught by a test case in isolation2/frozen_insert_crash.
* Also, we don't set frozen->frzflags as those are to be set only during vacuum.
*/
frozen.xmax = HeapTupleHeaderGetRawXmax(tup->t_data);
frozen.offset = ItemPointerGetOffsetNumber(&(tup->t_self));
frozen.t_infomask = tup->t_data->t_infomask;
frozen.t_infomask2 = tup->t_data->t_infomask2;

buffer = ReadBuffer(rel, ItemPointerGetBlockNumber(&(tup->t_self)));
LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);

page = (Page) BufferGetPage(buffer);

START_CRIT_SECTION();

MarkBufferDirty(buffer);

/* freeze the tuple in buffer */
htup = (HeapTupleHeader) PageGetItem(page, PageGetItemId(page, frozen.offset));
heap_execute_freeze_tuple(htup, &frozen);

/* WAL logging */
if (RelationNeedsWAL(rel))
{
XLogRecPtr recptr;

recptr = log_heap_freeze(rel, buffer, InvalidTransactionId /* cutoff_xid */,
&frozen, 1 /*ntuples*/);
PageSetLSN(page, recptr);
}

END_CRIT_SECTION();

UnlockReleaseBuffer(buffer);
}

/*
* For a given MultiXactId, return the hint bits that should be set in the
* tuple's infomask.
Expand Down Expand Up @@ -8927,8 +8985,11 @@ heap_xlog_freeze_page(XLogReaderState *record)
/*
* In Hot Standby mode, ensure that there's no queries running which still
* consider the frozen xids as running.
* GPDB: but do nothing if there is no valid cutoff xid, which means the
* record is not generated by vacuum but by specifically freezing a tuple
* (see heap_freeze_tuple_no_cutoff).
*/
if (InHotStandby)
if (InHotStandby && TransactionIdIsValid(cutoff_xid))
{
RelFileNode rnode;
TransactionId latestRemovedXid = cutoff_xid;
Expand Down
105 changes: 45 additions & 60 deletions src/backend/catalog/gp_fastsequence.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
#include "access/genam.h"
#include "access/htup.h"
#include "access/heapam.h"
#include "access/xact.h"
#include "utils/faultinjector.h"
#include "utils/syscache.h"

#include "catalog/gp_indexing.h"
Expand Down Expand Up @@ -85,63 +87,6 @@ InsertInitialFastSequenceEntries(Oid objid)
table_close(gp_fastsequence_rel, RowExclusiveLock);
}

/*
* InsertFastSequenceEntry
*
* Insert a new fast sequence entry for a given object. If the given
* object already exists in the table, this function replaces the old
* entry with a fresh initial value.
*/
void
InsertFastSequenceEntry(Oid objid, int64 objmod, int64 lastSequence)
{
Relation gp_fastsequence_rel;
ScanKeyData scankey[2];
SysScanDesc scan;
TupleDesc tupleDesc;
HeapTuple tuple = NULL;

/*
* Open and lock the gp_fastsequence catalog table.
*/
gp_fastsequence_rel = table_open(FastSequenceRelationId, RowExclusiveLock);
tupleDesc = RelationGetDescr(gp_fastsequence_rel);

/* SELECT * FROM gp_fastsequence WHERE objid = :1 AND objmod = :2 FOR UPDATE */
ScanKeyInit(&scankey[0],
Anum_gp_fastsequence_objid,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(objid));
ScanKeyInit(&scankey[1],
Anum_gp_fastsequence_objmod,
BTEqualStrategyNumber, F_INT8EQ,
Int64GetDatum(objmod));
scan = systable_beginscan(gp_fastsequence_rel, FastSequenceObjidObjmodIndexId, true,
NULL, 2, scankey);

tuple = systable_getnext(scan);
insert_or_update_fastsequence(gp_fastsequence_rel,
tuple,
tupleDesc,
objid,
objmod,
lastSequence);
systable_endscan(scan);

/*
* gp_fastsequence table locking for AO inserts uses bottom up approach
* meaning the locks are first acquired on the segments and later on the
* master.
* Hence, it is essential that we release the lock here to avoid
* any form of master-segment resource deadlock. E.g. A transaction
* trying to reindex gp_fastsequence has acquired a lock on it on the
* master but is blocked on the segment as another transaction which
* is an insert operation has acquired a lock first on segment and is
* trying to acquire a lock on the Master. Deadlock!
*/
table_close(gp_fastsequence_rel, RowExclusiveLock);
}

/*
* insert or update the existing fast sequence number for (objid, objmod).
*
Expand Down Expand Up @@ -175,7 +120,27 @@ insert_or_update_fastsequence(Relation gp_fastsequence_rel,

newTuple = heaptuple_form_to(tupleDesc, values, nulls, NULL, NULL);

CatalogTupleInsertFrozen(gp_fastsequence_rel, newTuple);
/* insert the tuple */
CatalogTupleInsert(gp_fastsequence_rel, newTuple);

#ifdef FAULT_INJECTOR
FaultInjector_InjectFaultIfSet(
"insert_fastsequence_before_freeze",
DDLNotSpecified,
"", //databaseName
RelationGetRelationName(gp_fastsequence_rel));
#endif

/* freeze the tuple */
heap_freeze_tuple_wal_logged(gp_fastsequence_rel, newTuple);

#ifdef FAULT_INJECTOR
FaultInjector_InjectFaultIfSet(
"insert_fastsequence_after_freeze",
DDLNotSpecified,
"", //databaseName
RelationGetRelationName(gp_fastsequence_rel));
#endif

heap_freetuple(newTuple);
}
Expand Down Expand Up @@ -280,7 +245,17 @@ int64 GetFastSequences(Oid objid, int64 objmod,

systable_endscan(scan);

/* Refer to the comment at the end of InsertFastSequenceEntry. */
/*
* gp_fastsequence table locking for AO inserts uses bottom up approach
* meaning the locks are first acquired on the segments and later on the
* master.
* Hence, it is essential that we release the lock here to avoid
* any form of master-segment resource deadlock. E.g. A transaction
* trying to reindex gp_fastsequence has acquired a lock on it on the
* master but is blocked on the segment as another transaction which
* is an insert operation has acquired a lock first on segment and is
* trying to acquire a lock on the Master. Deadlock!
*/
table_close(gp_fastsequence_rel, RowExclusiveLock);

return firstSequence;
Expand Down Expand Up @@ -341,7 +316,17 @@ int64 ReadLastSequence(Oid objid, int64 objmod)

systable_endscan(scan);

/* Refer to the comment at the end of InsertFastSequenceEntry. */
/*
* gp_fastsequence table locking for AO inserts uses bottom up approach
* meaning the locks are first acquired on the segments and later on the
* master.
* Hence, it is essential that we release the lock here to avoid
* any form of master-segment resource deadlock. E.g. A transaction
* trying to reindex gp_fastsequence has acquired a lock on it on the
* master but is blocked on the segment as another transaction which
* is an insert operation has acquired a lock first on segment and is
* trying to acquire a lock on the Master. Deadlock!
*/
heap_close(gp_fastsequence_rel, AccessShareLock);

return lastSequence;
Expand Down
1 change: 1 addition & 0 deletions src/include/access/heapam.h
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ extern void heap_inplace_update(Relation relation, HeapTuple tuple);
extern bool heap_freeze_tuple(HeapTupleHeader tuple,
TransactionId relfrozenxid, TransactionId relminmxid,
TransactionId cutoff_xid, TransactionId cutoff_multi);
extern void heap_freeze_tuple_wal_logged(Relation rel, HeapTuple tuple);
extern bool heap_tuple_needs_freeze(HeapTupleHeader tuple, TransactionId cutoff_xid,
MultiXactId cutoff_multi, Buffer buf);
extern bool heap_tuple_needs_eventual_freeze(HeapTupleHeader tuple);
Expand Down
8 changes: 0 additions & 8 deletions src/include/catalog/gp_fastsequence.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,6 @@ FOREIGN_KEY(objid REFERENCES pg_class(oid));
typedef FormData_gp_fastsequence *Form_gp_fastsequence;

#define NUM_FAST_SEQUENCES 100

/*
* Insert a new light-weight fast sequence entry for a given object.
*/
extern void InsertFastSequenceEntry(Oid objid, int64 objmod,
int64 lastSequence);


extern void InsertInitialFastSequenceEntries(Oid objid);

/*
Expand Down
Loading