Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commita8405cf

Browse files
committed
Acquire read lock on a buffer while writing it out, to prevent
concurrent modifications to the page by other backends.
1 parent384d94e commita8405cf

File tree

1 file changed

+45
-32
lines changed

1 file changed

+45
-32
lines changed

‎src/backend/storage/buffer/bufmgr.c

Lines changed: 45 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/storage/buffer/bufmgr.c,v 1.82 2000/06/08 22:37:20 momjian Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/storage/buffer/bufmgr.c,v 1.83 2000/09/25 04:11:09 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -429,17 +429,10 @@ BufferAlloc(Relation reln,
429429
inProgress= FALSE;
430430
for (buf= (BufferDesc*)NULL;buf== (BufferDesc*)NULL;)
431431
{
432-
433-
/* GetFreeBuffer will abort if it can't find a free buffer */
434432
buf=GetFreeBuffer();
435433

436-
/*
437-
* But it can return buf == NULL if we are in aborting transaction
438-
* now and so elog(ERROR,...) in GetFreeBuffer will not abort
439-
* again.
440-
*/
441-
if (buf==NULL)
442-
returnNULL;
434+
/* GetFreeBuffer will abort if it can't find a free buffer */
435+
Assert(buf);
443436

444437
/*
445438
* There should be exactly one pin on the buffer after it is
@@ -789,11 +782,21 @@ FlushBuffer(Buffer buffer, bool release)
789782
WaitIO(bufHdr,BufMgrLock);/* confirm end of IO */
790783
bufHdr->flags &= ~BM_JUST_DIRTIED;
791784
StartBufferIO(bufHdr, false);/* output IO start */
785+
792786
SpinRelease(BufMgrLock);
793787

788+
/*
789+
* Grab a read lock on the buffer to ensure that no
790+
* other backend changes its contents while we write it;
791+
* see comments in BufferSync().
792+
*/
793+
LockBuffer(BufferDescriptorGetBuffer(bufHdr),BUFFER_LOCK_SHARE);
794+
794795
status=smgrflush(DEFAULT_SMGR,bufrel,bufHdr->tag.blockNum,
795796
(char*)MAKE_PTR(bufHdr->data));
796797

798+
LockBuffer(BufferDescriptorGetBuffer(bufHdr),BUFFER_LOCK_UNLOCK);
799+
797800
/* drop relcache refcnt incremented by RelationIdCacheGetRelation */
798801
RelationDecrementReferenceCount(bufrel);
799802

@@ -1017,19 +1020,6 @@ ClearBufferDirtiedByMe(Buffer buffer, BufferDesc *bufHdr)
10171020
*that have been dirtied by the current xact and flush them to disk.
10181021
*We do *not* flush dirty buffers that have been dirtied by other xacts.
10191022
*(This is a substantial change from pre-7.0 behavior.)
1020-
*
1021-
*OLD COMMENTS (do these still apply?)
1022-
*
1023-
*Also, we need to be sure that no other transaction is
1024-
*modifying the page as we flush it.This is only a problem for objects
1025-
*that use a non-two-phase locking protocol, like btree indices.For
1026-
*those objects, we would like to set a write lock for the duration of
1027-
*our IO. Another possibility is to code updates to btree pages
1028-
*carefully, so that writing them out out of order cannot cause
1029-
*any unrecoverable errors.
1030-
*
1031-
*I don't want to think hard about this right now, so I will try
1032-
*to come back to it later.
10331023
*/
10341024
staticvoid
10351025
BufferSync()
@@ -1112,15 +1102,28 @@ BufferSync()
11121102
bufHdr->flags &= ~BM_JUST_DIRTIED;
11131103
StartBufferIO(bufHdr, false);/* output IO start */
11141104

1105+
SpinRelease(BufMgrLock);
1106+
1107+
/*
1108+
* Grab a read lock on the buffer to ensure that no
1109+
* other backend changes its contents while we write it;
1110+
* otherwise we could write a non-self-consistent page
1111+
* image to disk, which'd be bad news if the other
1112+
* transaction aborts before writing its changes.
1113+
*
1114+
* Note that we still need the BM_JUST_DIRTIED mechanism
1115+
* in case someone dirties the buffer just before we
1116+
* grab this lock or just after we release it.
1117+
*/
1118+
LockBuffer(BufferDescriptorGetBuffer(bufHdr),
1119+
BUFFER_LOCK_SHARE);
1120+
11151121
/*
11161122
* If we didn't have the reldesc in our local cache,
11171123
* write this page out using the 'blind write' storage
11181124
* manager routine. If we did find it, use the
11191125
* standard interface.
11201126
*/
1121-
#ifndefOPTIMIZE_SINGLE
1122-
SpinRelease(BufMgrLock);
1123-
#endif/* OPTIMIZE_SINGLE */
11241127
if (reln== (Relation)NULL)
11251128
{
11261129
status=smgrblindwrt(DEFAULT_SMGR,
@@ -1137,9 +1140,14 @@ BufferSync()
11371140
bufHdr->tag.blockNum,
11381141
(char*)MAKE_PTR(bufHdr->data));
11391142
}
1140-
#ifndefOPTIMIZE_SINGLE
1143+
1144+
/*
1145+
* Release the per-buffer readlock, reacquire BufMgrLock.
1146+
*/
1147+
LockBuffer(BufferDescriptorGetBuffer(bufHdr),
1148+
BUFFER_LOCK_UNLOCK);
1149+
11411150
SpinAcquire(BufMgrLock);
1142-
#endif/* OPTIMIZE_SINGLE */
11431151

11441152
UnpinBuffer(bufHdr);
11451153
if (status==SM_FAIL)
@@ -1522,9 +1530,14 @@ BufferReplace(BufferDesc *bufHdr)
15221530
/* To check if block content changed while flushing. - vadim 01/17/97 */
15231531
bufHdr->flags &= ~BM_JUST_DIRTIED;
15241532

1525-
#ifndefOPTIMIZE_SINGLE
15261533
SpinRelease(BufMgrLock);
1527-
#endif/* OPTIMIZE_SINGLE */
1534+
1535+
/*
1536+
* Grab a read lock on the buffer to ensure that no
1537+
* other backend changes its contents while we write it;
1538+
* see comments in BufferSync().
1539+
*/
1540+
LockBuffer(BufferDescriptorGetBuffer(bufHdr),BUFFER_LOCK_SHARE);
15281541

15291542
if (reln!= (Relation)NULL)
15301543
{
@@ -1540,9 +1553,9 @@ BufferReplace(BufferDesc *bufHdr)
15401553
false);/* no fsync */
15411554
}
15421555

1543-
#ifndefOPTIMIZE_SINGLE
1556+
LockBuffer(BufferDescriptorGetBuffer(bufHdr),BUFFER_LOCK_UNLOCK);
1557+
15441558
SpinAcquire(BufMgrLock);
1545-
#endif/* OPTIMIZE_SINGLE */
15461559

15471560
/* drop relcache refcnt incremented by RelationIdCacheGetRelation */
15481561
if (reln!= (Relation)NULL)

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp