diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c
index 4689a2f82ea0047cdbebd46c369435313ed33fa7..cd860e0450bc5098a7713cf9e7db1d9c2b9b6fab 100644
--- a/src/backend/access/transam/xact.c
+++ b/src/backend/access/transam/xact.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.41 1999/06/10 14:17:06 vadim Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.42 1999/06/29 04:54:46 vadim Exp $
  *
  * NOTES
  *		Transaction aborts can now occur two ways:
@@ -158,6 +158,8 @@
 #include <commands/sequence.h>
 #include <libpq/be-fsstubs.h>
 
+extern bool	SharedBufferChanged;
+
 static void AbortTransaction(void);
 static void AtAbort_Cache(void);
 static void AtAbort_Locks(void);
@@ -618,30 +620,36 @@ RecordTransactionCommit()
 	 */
 	xid = GetCurrentTransactionId();
 
-	/* ----------------
+	/* 
 	 *	flush the buffer manager pages.  Note: if we have stable
 	 *	main memory, dirty shared buffers are not flushed
 	 *	plai 8/7/90
-	 * ----------------
 	 */
 	leak = BufferPoolCheckLeak();
-	FlushBufferPool(!TransactionFlushEnabled());
-	if (leak)
-		ResetBufferPool();
 
-	/* ----------------
-	 *	have the transaction access methods record the status
-	 *	of this transaction id in the pg_log / pg_time relations.
-	 * ----------------
+	/*
+	 * If no one shared buffer was changed by this transaction then
+	 * we don't flush shared buffers and don't record commit status.
 	 */
-	TransactionIdCommit(xid);
+	if (SharedBufferChanged)
+	{
+		FlushBufferPool(!TransactionFlushEnabled());
+		if (leak)
+			ResetBufferPool();
+
+		/*
+		 *	have the transaction access methods record the status
+		 *	of this transaction id in the pg_log relation.
+		 */
+		TransactionIdCommit(xid);
+
+		/*
+		 *	Now write the log info to the disk too.
+		 */
+		leak = BufferPoolCheckLeak();
+		FlushBufferPool(!TransactionFlushEnabled());
+	}
 
-	/* ----------------
-	 *	Now write the log/time info to the disk too.
-	 * ----------------
-	 */
-	leak = BufferPoolCheckLeak();
-	FlushBufferPool(!TransactionFlushEnabled());
 	if (leak)
 		ResetBufferPool();
 }
@@ -731,19 +739,14 @@ RecordTransactionAbort()
 	 */
 	xid = GetCurrentTransactionId();
 
-	/* ----------------
-	 *	have the transaction access methods record the status
-	 *	of this transaction id in the pg_log / pg_time relations.
-	 * ----------------
+	/* 
+	 * Have the transaction access methods record the status of
+	 * this transaction id in the pg_log relation. We skip it
+	 * if no one shared buffer was changed by this transaction.
 	 */
-	TransactionIdAbort(xid);
+	if (SharedBufferChanged)
+		TransactionIdAbort(xid);
 
-	/* ----------------
-	 *	flush the buffer manager pages.  Note: if we have stable
-	 *	main memory, dirty shared buffers are not flushed
-	 *	plai 8/7/90
-	 * ----------------
-	 */
 	ResetBufferPool();
 }
 
@@ -965,6 +968,7 @@ CommitTransaction()
 	 * ----------------
 	 */
 	s->state = TRANS_DEFAULT;
+	SharedBufferChanged = false;	/* safest place to do it */
 
 }
 
@@ -1028,6 +1032,7 @@ AbortTransaction()
 	 * ----------------
 	 */
 	s->state = TRANS_DEFAULT;
+	SharedBufferChanged = false;	/* safest place to do it */
 }
 
 /* --------------------------------
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index 446917a4c5008d96d34f4cabc17b6dde2d627ccc..e81b2dfb96bab059578282f33570d8a2c30a7160 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/storage/buffer/bufmgr.c,v 1.55 1999/06/11 09:00:02 vadim Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/storage/buffer/bufmgr.c,v 1.56 1999/06/29 04:54:47 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -78,6 +78,15 @@ extern long int LocalBufferHitCount;
 extern long int BufferFlushCount;
 extern long int LocalBufferFlushCount;
 
+/*
+ * It's used to avoid disk writes for read-only transactions
+ * (i.e. when no one shared buffer was changed by transaction).
+ * We set it to true in WriteBuffer/WriteNoReleaseBuffer when
+ * marking shared buffer as dirty. We set it to false in xact.c
+ * after transaction is committed/aborted.
+ */
+bool			SharedBufferChanged = false;
+
 static int	WriteMode = BUFFER_LATE_WRITE;		/* Delayed write is
 												 * default */
 
@@ -699,6 +708,8 @@ WriteBuffer(Buffer buffer)
 
 		bufHdr = &BufferDescriptors[buffer - 1];
 
+		SharedBufferChanged = true;
+
 		SpinAcquire(BufMgrLock);
 		Assert(bufHdr->refcount > 0);
 		bufHdr->flags |= (BM_DIRTY | BM_JUST_DIRTIED);
@@ -810,6 +821,8 @@ FlushBuffer(Buffer buffer, bool release)
 	bufrel = RelationIdCacheGetRelation(bufHdr->tag.relId.relId);
 	Assert(bufrel != (Relation) NULL);
 
+	SharedBufferChanged = true;
+
 	/* To check if block content changed while flushing. - vadim 01/17/97 */
 	SpinAcquire(BufMgrLock);
 	bufHdr->flags &= ~BM_JUST_DIRTIED;
@@ -875,6 +888,8 @@ WriteNoReleaseBuffer(Buffer buffer)
 
 		bufHdr = &BufferDescriptors[buffer - 1];
 
+		SharedBufferChanged = true;
+
 		SpinAcquire(BufMgrLock);
 		bufHdr->flags |= (BM_DIRTY | BM_JUST_DIRTIED);
 		SpinRelease(BufMgrLock);