Fixed locking for non-MVCC snapshots

This commit is contained in:
Andrew Kane
2023-09-11 12:47:29 -07:00
parent b164833933
commit cb91de3332
3 changed files with 23 additions and 7 deletions

View File

@@ -40,6 +40,9 @@
#define IVFFLAT_METAPAGE_BLKNO 0 #define IVFFLAT_METAPAGE_BLKNO 0
#define IVFFLAT_HEAD_BLKNO 1 /* first list page */ #define IVFFLAT_HEAD_BLKNO 1 /* first list page */
/* Must correspond to page numbers since page lock is used */
#define IVFFLAT_SCAN_LOCK 0
/* IVFFlat parameters */ /* IVFFlat parameters */
#define IVFFLAT_DEFAULT_LISTS 100 #define IVFFLAT_DEFAULT_LISTS 100
#define IVFFLAT_MIN_LISTS 1 #define IVFFLAT_MIN_LISTS 1
@@ -246,6 +249,7 @@ typedef struct IvfflatScanOpaqueData
int probes; int probes;
int dimensions; int dimensions;
bool first; bool first;
bool hasLock;
Buffer buf; Buffer buf;
ItemPointerData heaptid; ItemPointerData heaptid;

View File

@@ -9,6 +9,7 @@
#include "miscadmin.h" #include "miscadmin.h"
#include "pgstat.h" #include "pgstat.h"
#include "storage/bufmgr.h" #include "storage/bufmgr.h"
#include "storage/lmgr.h"
/* /*
* Compare list distances * Compare list distances
@@ -263,6 +264,7 @@ ivfflatbeginscan(Relation index, int nkeys, int norderbys)
so = (IvfflatScanOpaque) palloc(offsetof(IvfflatScanOpaqueData, lists) + probes * sizeof(IvfflatScanList)); so = (IvfflatScanOpaque) palloc(offsetof(IvfflatScanOpaqueData, lists) + probes * sizeof(IvfflatScanList));
so->buf = InvalidBuffer; so->buf = InvalidBuffer;
so->first = true; so->first = true;
so->hasLock = false;
ItemPointerSetInvalid(&so->heaptid); ItemPointerSetInvalid(&so->heaptid);
so->probes = probes; so->probes = probes;
so->dimensions = dimensions; so->dimensions = dimensions;
@@ -347,6 +349,13 @@ ivfflatgettuple(IndexScanDesc scan, ScanDirection dir)
if (scan->orderByData == NULL) if (scan->orderByData == NULL)
elog(ERROR, "cannot scan ivfflat index without order"); elog(ERROR, "cannot scan ivfflat index without order");
/* Get a shared lock for non-MVCC snapshots */
if (!so->hasLock && !IsMVCCSnapshot(scan->xs_snapshot))
{
so->hasLock = true;
LockPage(scan->indexRelation, IVFFLAT_SCAN_LOCK, ShareLock);
}
if (scan->orderByData->sk_flags & SK_ISNULL) if (scan->orderByData->sk_flags & SK_ISNULL)
value = PointerGetDatum(InitVector(so->dimensions)); value = PointerGetDatum(InitVector(so->dimensions));
else else
@@ -422,6 +431,10 @@ ivfflatendscan(IndexScanDesc scan)
if (BufferIsValid(so->buf)) if (BufferIsValid(so->buf))
ReleaseBuffer(so->buf); ReleaseBuffer(so->buf);
/* Release lock */
if (so->hasLock)
UnlockPage(scan->indexRelation, IVFFLAT_SCAN_LOCK, ShareLock);
pairingheap_free(so->listQueue); pairingheap_free(so->listQueue);
tuplesort_end(so->sortstate); tuplesort_end(so->sortstate);

View File

@@ -3,6 +3,7 @@
#include "commands/vacuum.h" #include "commands/vacuum.h"
#include "ivfflat.h" #include "ivfflat.h"
#include "storage/bufmgr.h" #include "storage/bufmgr.h"
#include "storage/lmgr.h"
/* /*
* Bulk delete tuples from the index * Bulk delete tuples from the index
@@ -65,14 +66,10 @@ ivfflatbulkdelete(IndexVacuumInfo *info, IndexBulkDeleteResult *stats,
vacuum_delay_point(); vacuum_delay_point();
buf = ReadBufferExtended(index, MAIN_FORKNUM, searchPage, RBM_NORMAL, bas); /* Ensure no in-flight index scans for non-MVCC snapshots */
LockPage(index, IVFFLAT_SCAN_LOCK, ExclusiveLock);
/* buf = ReadBufferExtended(index, MAIN_FORKNUM, searchPage, RBM_NORMAL, bas);
* ambulkdelete cannot delete entries from pages that are
* pinned by other backends
*
* https://www.postgresql.org/docs/current/index-locking.html
*/
LockBufferForCleanup(buf); LockBufferForCleanup(buf);
state = GenericXLogStart(index); state = GenericXLogStart(index);
@@ -114,6 +111,8 @@ ivfflatbulkdelete(IndexVacuumInfo *info, IndexBulkDeleteResult *stats,
GenericXLogAbort(state); GenericXLogAbort(state);
UnlockReleaseBuffer(buf); UnlockReleaseBuffer(buf);
UnlockPage(index, IVFFLAT_SCAN_LOCK, ExclusiveLock);
} }
/* /*