Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit a453951

Browse files
committed
Take exclusive buffer lock in scan_heap() to eliminate some corner cases
in which invalid page data could be transiently written to disk by concurrent bgwriter activity. There doesn't seem any risk of loss of actual user data, but an empty page could possibly be left corrupt if a crash occurs before the correct data gets written out. Pointed out by Alvaro Herrera.
1 parent 4f915cd commit a453951

File tree

2 files changed

+13
-6
lines changed

2 files changed

+13
-6
lines changed

src/backend/commands/vacuum.c

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
*
1414
*
1515
* IDENTIFICATION
16-
* $PostgreSQL: pgsql/src/backend/commands/vacuum.c,v 1.314 2005/09/02 19:02:19 tgl Exp $
16+
* $PostgreSQL: pgsql/src/backend/commands/vacuum.c,v 1.315 2005/09/22 17:32:58 tgl Exp $
1717
*
1818
*-------------------------------------------------------------------------
1919
*/
@@ -1273,10 +1273,14 @@ scan_heap(VRelStats *vacrelstats, Relation onerel,
12731273
page = BufferGetPage(buf);
12741274

12751275
/*
1276-
* We don't bother to do LockBuffer(buf, BUFFER_LOCK_EXCLUSIVE)
1277-
* because we assume that holding exclusive lock on the relation
1278-
* will keep other backends from looking at the page.
1276+
* Since we are holding exclusive lock on the relation, no other
1277+
* backend can be accessing the page; however it is possible that
1278+
* the background writer will try to write the page if it's already
1279+
* marked dirty. To ensure that invalid data doesn't get written to
1280+
* disk, we must take exclusive buffer lock wherever we potentially
1281+
* modify pages.
12791282
*/
1283+
LockBuffer(buf, BUFFER_LOCK_EXCLUSIVE);
12801284

12811285
vacpage->blkno = blkno;
12821286
vacpage->offsets_used = 0;
@@ -1297,6 +1301,7 @@ scan_heap(VRelStats *vacrelstats, Relation onerel,
12971301
vacpagecopy = copy_vac_page(vacpage);
12981302
vpage_insert(vacuum_pages, vacpagecopy);
12991303
vpage_insert(fraged_pages, vacpagecopy);
1304+
LockBuffer(buf, BUFFER_LOCK_UNLOCK);
13001305
WriteBuffer(buf);
13011306
continue;
13021307
}
@@ -1312,6 +1317,7 @@ scan_heap(VRelStats *vacrelstats, Relation onerel,
13121317
vacpagecopy = copy_vac_page(vacpage);
13131318
vpage_insert(vacuum_pages, vacpagecopy);
13141319
vpage_insert(fraged_pages, vacpagecopy);
1320+
LockBuffer(buf, BUFFER_LOCK_UNLOCK);
13151321
ReleaseBuffer(buf);
13161322
continue;
13171323
}
@@ -1520,6 +1526,7 @@ scan_heap(VRelStats *vacrelstats, Relation onerel,
15201526
else
15211527
empty_end_pages = 0;
15221528

1529+
LockBuffer(buf, BUFFER_LOCK_UNLOCK);
15231530
if (pgchanged)
15241531
WriteBuffer(buf);
15251532
else

src/backend/commands/vacuumlazy.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
*
3232
*
3333
* IDENTIFICATION
34-
* $PostgreSQL: pgsql/src/backend/commands/vacuumlazy.c,v 1.58 2005/09/02 19:02:20 tgl Exp $
34+
* $PostgreSQL: pgsql/src/backend/commands/vacuumlazy.c,v 1.59 2005/09/22 17:32:58 tgl Exp $
3535
*
3636
*-------------------------------------------------------------------------
3737
*/
@@ -299,7 +299,7 @@ lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats,
299299
* or temp relation, but it's probably not worth the code space
300300
* to check that, since this surely isn't a critical path.
301301
*
302-
* Note: the comparable code in vacuum.c need not do all this
302+
* Note: the comparable code in vacuum.c need not worry
303303
* because it's got exclusive lock on the whole relation.
304304
*/
305305
LockBuffer(buf, BUFFER_LOCK_UNLOCK);

0 commit comments

Comments
 (0)