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.pull/5350/head
parent
52879fdc96
commit
5d8f74bd0b
|
@ -667,6 +667,7 @@ ReadFromBlock(Relation rel, BlockNumber blockno, uint32 offset, char *buf,
|
|||
uint32 len, bool force)
|
||||
{
|
||||
Buffer buffer = ReadBuffer(rel, blockno);
|
||||
LockBuffer(buffer, BUFFER_LOCK_SHARE);
|
||||
Page page = BufferGetPage(buffer);
|
||||
PageHeader phdr = (PageHeader) page;
|
||||
|
||||
|
@ -678,7 +679,7 @@ ReadFromBlock(Relation rel, BlockNumber blockno, uint32 offset, char *buf,
|
|||
}
|
||||
|
||||
memcpy_s(buf, len, page + offset, len);
|
||||
ReleaseBuffer(buffer);
|
||||
UnlockReleaseBuffer(buffer);
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue