mirror of https://github.com/citusdata/citus.git
(Share) Lock buffer page when reading from columnar storage (#5338)
Under high write concurrency, we were sometimes reading columnar
metapage as all zeros.
In `WriteToBlock()`, if `clear == true`, then it will clear the page before
writing the new one, rather than just adding data to the page. That
means any concurrent connection that is holding only a pin will be
able to see the all-zero state between the `InitPage()` and the
`memcpy_s()`.
Moreover, postgres/storage/buffer/README states that:
> Buffer access rules:
>
> 1. To scan a page for tuples, one must hold a pin and either shared or
> exclusive content lock. To examine the commit status (XIDs and status bits)
> of a tuple in a shared buffer, one must likewise hold a pin and either shared
> or exclusive lock.
For those reasons, we have to make sure to never keep a pin on the
page without (at least) the shared lock, to avoid having such problems.
(cherry picked from commit 5d8f74bd0b
)
partitioned-index
parent
819ac372e0
commit
6fe7c32d9f
|
@ -667,6 +667,7 @@ ReadFromBlock(Relation rel, BlockNumber blockno, uint32 offset, char *buf,
|
||||||
uint32 len, bool force)
|
uint32 len, bool force)
|
||||||
{
|
{
|
||||||
Buffer buffer = ReadBuffer(rel, blockno);
|
Buffer buffer = ReadBuffer(rel, blockno);
|
||||||
|
LockBuffer(buffer, BUFFER_LOCK_SHARE);
|
||||||
Page page = BufferGetPage(buffer);
|
Page page = BufferGetPage(buffer);
|
||||||
PageHeader phdr = (PageHeader) page;
|
PageHeader phdr = (PageHeader) page;
|
||||||
|
|
||||||
|
@ -678,7 +679,7 @@ ReadFromBlock(Relation rel, BlockNumber blockno, uint32 offset, char *buf,
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy_s(buf, len, page + offset, len);
|
memcpy_s(buf, len, page + offset, len);
|
||||||
ReleaseBuffer(buffer);
|
UnlockReleaseBuffer(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue