1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-23 03:21:12 +03:00

Repair very-low-probability race condition between relation extension

and VACUUM: in the interval between adding a new page to the relation
and formatting it, it was possible for VACUUM to come along and decide
it should format the page too.  Though not harmful in itself, this would
cause data loss if a third transaction were able to insert tuples into
the vacuumed page before the original extender got control back.
This commit is contained in:
Tom Lane
2005-05-07 21:32:24 +00:00
parent b72e5fa17b
commit 30f540be43
4 changed files with 73 additions and 18 deletions

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/heap/hio.c,v 1.55 2005/04/29 22:28:23 tgl Exp $
* $PostgreSQL: pgsql/src/backend/access/heap/hio.c,v 1.56 2005/05/07 21:32:23 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -241,13 +241,6 @@ RelationGetBufferForTuple(Relation relation, Size len,
*/
buffer = ReadBuffer(relation, P_NEW);
/*
* Release the file-extension lock; it's now OK for someone else to
* extend the relation some more.
*/
if (needLock)
UnlockRelationForExtension(relation, ExclusiveLock);
/*
* We can be certain that locking the otherBuffer first is OK, since
* it must have a lower page number.
@ -256,9 +249,22 @@ RelationGetBufferForTuple(Relation relation, Size len,
LockBuffer(otherBuffer, BUFFER_LOCK_EXCLUSIVE);
/*
* We need to initialize the empty new page.
* Now acquire lock on the new page.
*/
LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
/*
* Release the file-extension lock; it's now OK for someone else to
* extend the relation some more. Note that we cannot release this
* lock before we have buffer lock on the new page, or we risk a
* race condition against vacuumlazy.c --- see comments therein.
*/
if (needLock)
UnlockRelationForExtension(relation, ExclusiveLock);
/*
* We need to initialize the empty new page.
*/
pageHeader = (Page) BufferGetPage(buffer);
Assert(PageIsNew((PageHeader) pageHeader));
PageInit(pageHeader, BufferGetPageSize(buffer), 0);