Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit c6ade7a

Browse filesBrowse files
committed
Prevent deadlock in ginRedoDeletePage()
On standby ginRedoDeletePage() can work concurrently with read-only queries. Those queries can traverse posting tree in two ways. 1) Using rightlinks by ginStepRight(), which locks the next page before unlocking its left sibling. 2) Using downlinks by ginFindLeafPage(), which locks at most one page at time. Original lock order was: page, parent, left sibling. That lock order can deadlock with ginStepRight(). In order to prevent deadlock this commit changes lock order to: left sibling, page, parent. Note, that position of parent in locking order seems insignificant, because we only lock one page at time while traversing downlinks. Reported-by: Chen Huajun Diagnosed-by: Chen Huajun, Peter Geoghegan, Andrey Borodin Discussion: https://postgr.es/m/31a702a.14dd.166c1366ac1.Coremail.chjischj%40163.com Author: Alexander Korotkov Backpatch-through: 9.4
1 parent fd83c83 commit c6ade7a
Copy full SHA for c6ade7a

File tree

1 file changed

+13
-9
lines changed
Filter options

1 file changed

+13
-9
lines changed

‎src/backend/access/gin/ginxlog.c

Copy file name to clipboardExpand all lines: src/backend/access/gin/ginxlog.c
+13-9Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,19 @@ ginRedoDeletePage(XLogReaderState *record)
513513
Buffer lbuffer;
514514
Page page;
515515

516+
/*
517+
* Lock left page first in order to prevent possible deadlock with
518+
* ginStepRight().
519+
*/
520+
if (XLogReadBufferForRedo(record, 2, &lbuffer) == BLK_NEEDS_REDO)
521+
{
522+
page = BufferGetPage(lbuffer);
523+
Assert(GinPageIsData(page));
524+
GinPageGetOpaque(page)->rightlink = data->rightLink;
525+
PageSetLSN(page, lsn);
526+
MarkBufferDirty(lbuffer);
527+
}
528+
516529
if (XLogReadBufferForRedo(record, 0, &dbuffer) == BLK_NEEDS_REDO)
517530
{
518531
page = BufferGetPage(dbuffer);
@@ -532,15 +545,6 @@ ginRedoDeletePage(XLogReaderState *record)
532545
MarkBufferDirty(pbuffer);
533546
}
534547

535-
if (XLogReadBufferForRedo(record, 2, &lbuffer) == BLK_NEEDS_REDO)
536-
{
537-
page = BufferGetPage(lbuffer);
538-
Assert(GinPageIsData(page));
539-
GinPageGetOpaque(page)->rightlink = data->rightLink;
540-
PageSetLSN(page, lsn);
541-
MarkBufferDirty(lbuffer);
542-
}
543-
544548
if (BufferIsValid(lbuffer))
545549
UnlockReleaseBuffer(lbuffer);
546550
if (BufferIsValid(pbuffer))

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.