@@ -649,55 +649,37 @@ btree_xlog_unlink_page(uint8 info, XLogReaderState *record)
649
649
xl_btree_unlink_page * xlrec = (xl_btree_unlink_page * ) XLogRecGetData (record );
650
650
BlockNumber leftsib ;
651
651
BlockNumber rightsib ;
652
- Buffer buffer ;
652
+ Buffer leafbuf , lbuff = InvalidBuffer , rbuff , buff ;
653
653
Page page ;
654
654
BTPageOpaque pageop ;
655
655
656
656
leftsib = xlrec -> leftsib ;
657
657
rightsib = xlrec -> rightsib ;
658
658
659
659
/*
660
- * In normal operation, we would lock all the pages this WAL record
661
- * touches before changing any of them. In WAL replay, it should be okay
662
- * to lock just one page at a time, since no concurrent index updates can
663
- * be happening, and readers should not care whether they arrive at the
664
- * target page or not (since it's surely empty).
660
+ * We have to lock the pages we need to modify in the moving right order.
661
+ * Else we will go into the race against _bt_walk_left.
665
662
*/
666
663
667
- /* Fix left-link of right sibling */
668
- if (XLogReadBufferForRedo (record , 2 , & buffer ) == BLK_NEEDS_REDO )
669
- {
670
- page = (Page ) BufferGetPage (buffer );
671
- pageop = (BTPageOpaque ) PageGetSpecialPointer (page );
672
- pageop -> btpo_prev = leftsib ;
673
-
674
- PageSetLSN (page , lsn );
675
- MarkBufferDirty (buffer );
676
- }
677
- if (BufferIsValid (buffer ))
678
- UnlockReleaseBuffer (buffer );
679
-
680
664
/* Fix right-link of left sibling, if any */
681
665
if (leftsib != P_NONE )
682
666
{
683
- if (XLogReadBufferForRedo (record , 1 , & buffer ) == BLK_NEEDS_REDO )
667
+ if (XLogReadBufferForRedo (record , 1 , & lbuff ) == BLK_NEEDS_REDO )
684
668
{
685
- page = (Page ) BufferGetPage (buffer );
669
+ page = (Page ) BufferGetPage (lbuff );
686
670
pageop = (BTPageOpaque ) PageGetSpecialPointer (page );
687
671
pageop -> btpo_next = rightsib ;
688
672
689
673
PageSetLSN (page , lsn );
690
- MarkBufferDirty (buffer );
674
+ MarkBufferDirty (lbuff );
691
675
}
692
- if (BufferIsValid (buffer ))
693
- UnlockReleaseBuffer (buffer );
694
676
}
695
677
696
678
/* Rewrite target page as empty deleted page */
697
- buffer = XLogInitBufferForRedo (record , 0 );
698
- page = (Page ) BufferGetPage (buffer );
679
+ buff = XLogInitBufferForRedo (record , 0 );
680
+ page = (Page ) BufferGetPage (buff );
699
681
700
- _bt_pageinit (page , BufferGetPageSize (buffer ));
682
+ _bt_pageinit (page , BufferGetPageSize (buff ));
701
683
pageop = (BTPageOpaque ) PageGetSpecialPointer (page );
702
684
703
685
pageop -> btpo_prev = leftsib ;
@@ -707,9 +689,26 @@ btree_xlog_unlink_page(uint8 info, XLogReaderState *record)
707
689
pageop -> btpo_cycleid = 0 ;
708
690
709
691
PageSetLSN (page , lsn );
710
- MarkBufferDirty (buffer );
711
- UnlockReleaseBuffer (buffer );
692
+ MarkBufferDirty (buff );
693
+
694
+ /* Fix left-link of right sibling */
695
+ if (XLogReadBufferForRedo (record , 2 , & rbuff ) == BLK_NEEDS_REDO )
696
+ {
697
+ page = (Page ) BufferGetPage (rbuff );
698
+ pageop = (BTPageOpaque ) PageGetSpecialPointer (page );
699
+ pageop -> btpo_prev = leftsib ;
712
700
701
+ PageSetLSN (page , lsn );
702
+ MarkBufferDirty (rbuff );
703
+ }
704
+
705
+ /* Release all buffers */
706
+ if (BufferIsValid (lbuff ))
707
+ UnlockReleaseBuffer (lbuff );
708
+ UnlockReleaseBuffer (buff );
709
+ if (BufferIsValid (rbuff ))
710
+ UnlockReleaseBuffer (rbuff );
711
+
713
712
/*
714
713
* If we deleted a parent of the targeted leaf page, instead of the leaf
715
714
* itself, update the leaf to point to the next remaining child in the
@@ -723,10 +722,10 @@ btree_xlog_unlink_page(uint8 info, XLogReaderState *record)
723
722
*/
724
723
IndexTupleData trunctuple ;
725
724
726
- buffer = XLogInitBufferForRedo (record , 3 );
727
- page = (Page ) BufferGetPage (buffer );
725
+ leafbuf = XLogInitBufferForRedo (record , 3 );
726
+ page = (Page ) BufferGetPage (leafbuf );
728
727
729
- _bt_pageinit (page , BufferGetPageSize (buffer ));
728
+ _bt_pageinit (page , BufferGetPageSize (leafbuf ));
730
729
pageop = (BTPageOpaque ) PageGetSpecialPointer (page );
731
730
732
731
pageop -> btpo_flags = BTP_HALF_DEAD | BTP_LEAF ;
@@ -745,8 +744,8 @@ btree_xlog_unlink_page(uint8 info, XLogReaderState *record)
745
744
elog (ERROR , "could not add dummy high key to half-dead page" );
746
745
747
746
PageSetLSN (page , lsn );
748
- MarkBufferDirty (buffer );
749
- UnlockReleaseBuffer (buffer );
747
+ MarkBufferDirty (leafbuf );
748
+ UnlockReleaseBuffer (leafbuf );
750
749
}
751
750
752
751
/* Update metapage if needed */
0 commit comments