aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAmit Kapila <akapila@postgresql.org>2019-02-02 08:46:32 +0530
committerAmit Kapila <akapila@postgresql.org>2019-02-02 08:46:32 +0530
commit1ca33fc7b5111748222d1ac20b8b8ebb49bb75e6 (patch)
tree00994835e5175210143218b8b4cf4e7bce5ea3fe
parent478e0069fb8bc30d7e0c1a8fc390ed041e1b67c9 (diff)
downloadpostgresql-1ca33fc7b5111748222d1ac20b8b8ebb49bb75e6.tar.gz
postgresql-1ca33fc7b5111748222d1ac20b8b8ebb49bb75e6.zip
Avoid possible deadlock while locking multiple heap pages.
To avoid deadlock, backend acquires a lock on heap pages in block number order. In certain cases, lock on heap pages is dropped and reacquired. In this case, the locks are dropped for reading in corresponding VM page/s. The issue is we re-acquire locks in bufferId order whereas the intention was to acquire in blockid order. This commit ensures that we will always acquire locks on heap pages in blockid order. Reported-by: Nishant Fnu Author: Nishant Fnu Reviewed-by: Amit Kapila and Robert Haas Backpatch-through: 9.4 Discussion: https://postgr.es/m/5883C831-2ED1-47C8-BFAC-2D5BAE5A8CAE@amazon.com
-rw-r--r--src/backend/access/heap/hio.c8
1 files changed, 4 insertions, 4 deletions
diff --git a/src/backend/access/heap/hio.c b/src/backend/access/heap/hio.c
index 13e3bdca50d..7f56c98fd49 100644
--- a/src/backend/access/heap/hio.c
+++ b/src/backend/access/heap/hio.c
@@ -115,8 +115,8 @@ ReadBufferBI(Relation relation, BlockNumber targetBlock,
* visibility map page, if we haven't already got one.
*
* buffer2 may be InvalidBuffer, if only one buffer is involved. buffer1
- * must not be InvalidBuffer. If both buffers are specified, buffer1 must
- * be less than buffer2.
+ * must not be InvalidBuffer. If both buffers are specified, block1 must
+ * be less than block2.
*/
static void
GetVisibilityMapPins(Relation relation, Buffer buffer1, Buffer buffer2,
@@ -127,7 +127,7 @@ GetVisibilityMapPins(Relation relation, Buffer buffer1, Buffer buffer2,
bool need_to_pin_buffer2;
Assert(BufferIsValid(buffer1));
- Assert(buffer2 == InvalidBuffer || buffer1 <= buffer2);
+ Assert(buffer2 == InvalidBuffer || block1 <= block2);
while (1)
{
@@ -449,7 +449,7 @@ loop:
* done a bit of extra work for no gain, but there's no real harm
* done.
*/
- if (otherBuffer == InvalidBuffer || buffer <= otherBuffer)
+ if (otherBuffer == InvalidBuffer || targetBlock <= otherBlock)
GetVisibilityMapPins(relation, buffer, otherBuffer,
targetBlock, otherBlock, vmbuffer,
vmbuffer_other);