1
0
mirror of https://github.com/postgres/postgres.git synced 2025-08-31 17:02: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

@@ -31,7 +31,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/vacuumlazy.c,v 1.52 2005/03/25 22:51:31 tgl Exp $
* $PostgreSQL: pgsql/src/backend/commands/vacuumlazy.c,v 1.53 2005/05/07 21:32:24 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -280,8 +280,30 @@ lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats,
if (PageIsNew(page))
{
/* Not sure we still need to handle this case, but... */
/*
* An all-zeroes page could be left over if a backend extends
* the relation but crashes before initializing the page.
* Reclaim such pages for use.
*
* We have to be careful here because we could be looking at
* a page that someone has just added to the relation and not
* yet been able to initialize (see RelationGetBufferForTuple).
* To interlock against that, release the buffer read lock
* (which we must do anyway) and grab the relation extension
* lock before re-locking in exclusive mode. If the page is
* still uninitialized by then, it must be left over from a
* crashed backend, and we can initialize it.
*
* We don't really need the relation lock when this is a new
* or temp relation, but it's probably not worth the code space
* to check that, since this surely isn't a critical path.
*
* Note: the comparable code in vacuum.c need not do all this
* because it's got exclusive lock on the whole relation.
*/
LockBuffer(buf, BUFFER_LOCK_UNLOCK);
LockRelationForExtension(onerel, ExclusiveLock);
UnlockRelationForExtension(onerel, ExclusiveLock);
LockBuffer(buf, BUFFER_LOCK_EXCLUSIVE);
if (PageIsNew(page))
{