]> granicus.if.org Git - postgresql/commitdiff
Fix replay of XLOG_HEAP_NEWPAGE WAL records to pay attention to the forknum
authorTom Lane <tgl@sss.pgh.pa.us>
Sun, 2 May 2010 22:28:05 +0000 (22:28 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Sun, 2 May 2010 22:28:05 +0000 (22:28 +0000)
field of the WAL record.  The previous coding always wrote to the main fork,
resulting in data corruption if the page was meant to go into a non-default
fork.

At present, the only operation that can produce such WAL records is
ALTER TABLE/INDEX SET TABLESPACE when executed with archive_mode = on.
Data corruption would be observed on standby slaves, and could occur on the
master as well if a database crash and recovery occurred after committing
the ALTER and before the next checkpoint.  Per report from Gordon Shannon.

Back-patch to 8.4; the problem doesn't exist in earlier branches because
we didn't have a concept of multiple relation forks then.

src/backend/access/heap/heapam.c

index 93848942c7f723a9d4876d22b7a1fde85fabd0d1..78a3f2738c59798f746534b2677f28cbfea8a8e5 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.289 2010/04/22 02:15:45 sriggs Exp $
+ *       $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.290 2010/05/02 22:28:05 tgl Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -4257,8 +4257,10 @@ heap_xlog_newpage(XLogRecPtr lsn, XLogRecord *record)
         * Note: the NEWPAGE log record is used for both heaps and indexes, so do
         * not do anything that assumes we are touching a heap.
         */
-       buffer = XLogReadBuffer(xlrec->node, xlrec->blkno, true);
+       buffer = XLogReadBufferExtended(xlrec->node, xlrec->forknum, xlrec->blkno,
+                                                                       RBM_ZERO);
        Assert(BufferIsValid(buffer));
+       LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
        page = (Page) BufferGetPage(buffer);
 
        Assert(record->xl_len == SizeOfHeapNewpage + BLCKSZ);