postgres.git / summary / log / commit / refs

commit    6a2c9c6331359c48e4fb883ff2513ef7da9bc581
Author:   Amit Kapila <akapila@postgresql.org>
Date:     Sat Feb 02 03:46:35 2019 +0000
First released in: 12.0, 9.4.21, 9.5.16, 9.6.12, 10.7, 11.2

    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


src/backend/access/heap/hio.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/backend/access/heap/hio.c b/src/backend/access/heap/hio.c index 6db73bf9d00..0e3d999c128 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) { @@ -379,7 +379,7 @@ RelationGetBufferForTuple(Relation relation, Size len, * 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); [parent: 90f1ba7ecf01]