bm-flush-xlog-paranoid.patch
application/octet-stream
Filename: bm-flush-xlog-paranoid.patch
Type: application/octet-stream
Part: 0
Message:
Re: unlogged tables vs. GIST
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: unified
| File | + | − |
|---|---|---|
| src/backend/storage/buffer/bufmgr.c | 33 | 19 |
| src/include/storage/buf_internals.h | 1 | 0 |
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index 56569cc..d09af92 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -85,7 +85,7 @@ static volatile BufferDesc *PinCountWaitBuf = NULL;
static Buffer ReadBuffer_common(SMgrRelation reln,
ForkNumber forkNum, BlockNumber blockNum,
ReadBufferMode mode, BufferAccessStrategy strategy,
- bool *hit);
+ bool flush_xlog, bool *hit);
static bool PinBuffer(volatile BufferDesc *buf, BufferAccessStrategy strategy);
static void PinBuffer_Locked(volatile BufferDesc *buf);
static void UnpinBuffer(volatile BufferDesc *buf, bool fixOwner);
@@ -99,9 +99,10 @@ static void shared_buffer_write_error_callback(void *arg);
static void local_buffer_write_error_callback(void *arg);
static volatile BufferDesc *BufferAlloc(SMgrRelation smgr, ForkNumber forkNum,
BlockNumber blockNum,
- BufferAccessStrategy strategy,
+ BufferAccessStrategy strategy, bool flush_xlog,
bool *foundPtr);
-static void FlushBuffer(volatile BufferDesc *buf, SMgrRelation reln);
+static void FlushBuffer(volatile BufferDesc *buf, SMgrRelation reln,
+ bool flush_xlog);
static void AtProcExit_Buffers(int code, Datum arg);
@@ -242,7 +243,7 @@ ReadBufferExtended(Relation reln, ForkNumber forkNum, BlockNumber blockNum,
*/
pgstat_count_buffer_read(reln);
buf = ReadBuffer_common(reln->rd_smgr, forkNum, blockNum,
- mode, strategy, &hit);
+ mode, strategy, RelationNeedsWAL(reln), &hit);
if (hit)
pgstat_count_buffer_hit(reln);
return buf;
@@ -254,9 +255,9 @@ ReadBufferExtended(Relation reln, ForkNumber forkNum, BlockNumber blockNum,
* a relcache entry for the relation.
*
* NB: At present, this function may not be used on temporary relations, which
- * is OK, because we only use it during XLOG replay. If in the future we
- * want to use it on temporary relations, we could pass the backend ID as an
- * additional parameter.
+ * is OK, because we only use it during XLOG replay. We are therefore entitled
+ * to assume that the backend ID is InvalidBackendId and that XLOG flush is
+ * required.
*/
Buffer
ReadBufferWithoutRelcache(RelFileNode rnode, ForkNumber forkNum,
@@ -267,7 +268,8 @@ ReadBufferWithoutRelcache(RelFileNode rnode, ForkNumber forkNum,
SMgrRelation smgr = smgropen(rnode, InvalidBackendId);
- return ReadBuffer_common(smgr, forkNum, blockNum, mode, strategy, &hit);
+ return ReadBuffer_common(smgr, forkNum, blockNum, mode, strategy,
+ true, &hit);
}
@@ -279,7 +281,7 @@ ReadBufferWithoutRelcache(RelFileNode rnode, ForkNumber forkNum,
static Buffer
ReadBuffer_common(SMgrRelation smgr, ForkNumber forkNum,
BlockNumber blockNum, ReadBufferMode mode,
- BufferAccessStrategy strategy, bool *hit)
+ BufferAccessStrategy strategy, bool flush_xlog, bool *hit)
{
volatile BufferDesc *bufHdr;
Block bufBlock;
@@ -319,7 +321,8 @@ ReadBuffer_common(SMgrRelation smgr, ForkNumber forkNum,
* lookup the buffer. IO_IN_PROGRESS is set if the requested block is
* not currently in memory.
*/
- bufHdr = BufferAlloc(smgr, forkNum, blockNum, strategy, &found);
+ bufHdr = BufferAlloc(smgr, forkNum, blockNum, strategy, flush_xlog,
+ &found);
if (found)
pgBufferUsage.shared_blks_hit++;
else
@@ -502,7 +505,7 @@ ReadBuffer_common(SMgrRelation smgr, ForkNumber forkNum,
static volatile BufferDesc *
BufferAlloc(SMgrRelation smgr, ForkNumber forkNum,
BlockNumber blockNum,
- BufferAccessStrategy strategy,
+ BufferAccessStrategy strategy, bool flush_xlog,
bool *foundPtr)
{
BufferTag newTag; /* identity of requested block */
@@ -644,7 +647,7 @@ BufferAlloc(SMgrRelation smgr, ForkNumber forkNum,
smgr->smgr_rnode.node.dbNode,
smgr->smgr_rnode.node.relNode);
- FlushBuffer(buf, NULL);
+ FlushBuffer(buf, NULL, (oldFlags & BM_FLUSH_XLOG) != 0);
LWLockRelease(buf->content_lock);
TRACE_POSTGRESQL_BUFFER_WRITE_DIRTY_DONE(forkNum, blockNum,
@@ -798,7 +801,7 @@ BufferAlloc(SMgrRelation smgr, ForkNumber forkNum,
*/
buf->tag = newTag;
buf->flags &= ~(BM_VALID | BM_DIRTY | BM_JUST_DIRTIED | BM_CHECKPOINT_NEEDED | BM_IO_ERROR);
- buf->flags |= BM_TAG_VALID;
+ buf->flags |= BM_TAG_VALID | (flush_xlog ? BM_FLUSH_XLOG : 0);
buf->usage_count = 1;
UnlockBufHdr(buf);
@@ -1574,6 +1577,7 @@ SyncOneBuffer(int buf_id, bool skip_recently_used)
{
volatile BufferDesc *bufHdr = &BufferDescriptors[buf_id];
int result = 0;
+ bool flush_xlog;
/*
* Check whether buffer needs writing.
@@ -1602,6 +1606,9 @@ SyncOneBuffer(int buf_id, bool skip_recently_used)
return result;
}
+ /* remember flush xlog flag */
+ flush_xlog = (bufHdr->flags & BM_FLUSH_XLOG) != 0;
+
/*
* Pin it, share-lock it, write it. (FlushBuffer will do nothing if the
* buffer is clean by the time we've locked it.)
@@ -1609,7 +1616,7 @@ SyncOneBuffer(int buf_id, bool skip_recently_used)
PinBuffer_Locked(bufHdr);
LWLockAcquire(bufHdr->content_lock, LW_SHARED);
- FlushBuffer(bufHdr, NULL);
+ FlushBuffer(bufHdr, NULL, flush_xlog);
LWLockRelease(bufHdr->content_lock);
UnpinBuffer(bufHdr, true);
@@ -1820,7 +1827,7 @@ BufferGetTag(Buffer buffer, RelFileNode *rnode, ForkNumber *forknum,
* as the second parameter. If not, pass NULL.
*/
static void
-FlushBuffer(volatile BufferDesc *buf, SMgrRelation reln)
+FlushBuffer(volatile BufferDesc *buf, SMgrRelation reln, bool flush_xlog)
{
XLogRecPtr recptr;
ErrorContextCallback errcontext;
@@ -1854,8 +1861,11 @@ FlushBuffer(volatile BufferDesc *buf, SMgrRelation reln)
* rule that log updates must hit disk before any of the data-file changes
* they describe do.
*/
- recptr = BufferGetLSN(buf);
- XLogFlush(recptr);
+ if (flush_xlog)
+ {
+ recptr = BufferGetLSN(buf);
+ XLogFlush(recptr);
+ }
/*
* Now it's safe to write buffer to disk. Note that no one else should
@@ -2067,6 +2077,7 @@ FlushRelationBuffers(Relation rel)
{
int i;
volatile BufferDesc *bufHdr;
+ bool flush_xlog;
/* Open rel at the smgr level if not already done */
RelationOpenSmgr(rel);
@@ -2113,9 +2124,10 @@ FlushRelationBuffers(Relation rel)
if (RelFileNodeEquals(bufHdr->tag.rnode, rel->rd_node) &&
(bufHdr->flags & BM_VALID) && (bufHdr->flags & BM_DIRTY))
{
+ flush_xlog = (bufHdr->flags & BM_FLUSH_XLOG) != 0;
PinBuffer_Locked(bufHdr);
LWLockAcquire(bufHdr->content_lock, LW_SHARED);
- FlushBuffer(bufHdr, rel->rd_smgr);
+ FlushBuffer(bufHdr, rel->rd_smgr, flush_xlog);
LWLockRelease(bufHdr->content_lock);
UnpinBuffer(bufHdr, true);
}
@@ -2144,6 +2156,7 @@ FlushDatabaseBuffers(Oid dbid)
{
int i;
volatile BufferDesc *bufHdr;
+ bool flush_xlog;
/* Make sure we can handle the pin inside the loop */
ResourceOwnerEnlargeBuffers(CurrentResourceOwner);
@@ -2155,9 +2168,10 @@ FlushDatabaseBuffers(Oid dbid)
if (bufHdr->tag.rnode.dbNode == dbid &&
(bufHdr->flags & BM_VALID) && (bufHdr->flags & BM_DIRTY))
{
+ flush_xlog = (bufHdr->flags & BM_FLUSH_XLOG) != 0;
PinBuffer_Locked(bufHdr);
LWLockAcquire(bufHdr->content_lock, LW_SHARED);
- FlushBuffer(bufHdr, NULL);
+ FlushBuffer(bufHdr, NULL, flush_xlog);
LWLockRelease(bufHdr->content_lock);
UnpinBuffer(bufHdr, true);
}
diff --git a/src/include/storage/buf_internals.h b/src/include/storage/buf_internals.h
index 0c18fb5..b29c618 100644
--- a/src/include/storage/buf_internals.h
+++ b/src/include/storage/buf_internals.h
@@ -37,6 +37,7 @@
#define BM_JUST_DIRTIED (1 << 5) /* dirtied since write started */
#define BM_PIN_COUNT_WAITER (1 << 6) /* have waiter for sole pin */
#define BM_CHECKPOINT_NEEDED (1 << 7) /* must write for checkpoint */
+#define BM_FLUSH_XLOG (1 << 8) /* must flush xlog */
typedef bits16 BufFlags;