diff --git a/doc/src/sgml/ref/begin.sgml b/doc/src/sgml/ref/begin.sgml
index bf1195f52772882fbf4845f3c0d2fa39bdfa88fb..741d8aa997a14ed8625fed933477191a2e0e96ef 100644
--- a/doc/src/sgml/ref/begin.sgml
+++ b/doc/src/sgml/ref/begin.sgml
@@ -1,5 +1,5 @@
 <!--
-$PostgreSQL: pgsql/doc/src/sgml/ref/begin.sgml,v 1.32 2004/08/08 01:48:31 momjian Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/begin.sgml,v 1.33 2004/08/12 21:00:21 tgl Exp $
 PostgreSQL documentation
 -->
 
@@ -20,9 +20,12 @@ PostgreSQL documentation
 
  <refsynopsisdiv>
 <synopsis>
-BEGIN [ WORK | TRANSACTION ]
-    [ ISOLATION LEVEL { READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE } ]
-    [ READ WRITE | READ ONLY ]
+BEGIN [ WORK | TRANSACTION ] [ <replaceable class="parameter">transaction_mode</replaceable> [, ...] ]
+
+where <replaceable class="parameter">transaction_mode</replaceable> is one of:
+
+    ISOLATION LEVEL { SERIALIZABLE | REPEATABLE READ | READ COMMITTED | READ UNCOMMITTED }
+    READ WRITE | READ ONLY
 </synopsis>
  </refsynopsisdiv>
  
@@ -101,8 +104,13 @@ BEGIN [ WORK | TRANSACTION ]
    Issuing <command>BEGIN</> when already inside a transaction block will
    provoke a warning message.  The state of the transaction is not affected.
    To nest transactions within a transaction block, use savepoints 
-   (See <xref linkend="sql-start-transaction" endterm="sql-start-transaction-title">
-   for more information).
+   (see <xref linkend="sql-savepoint" endterm="sql-savepoint-title">).
+  </para>
+
+  <para>
+   For reasons of backwards compatibility, the commas between successive
+   <replaceable class="parameter">transaction_modes</replaceable> may be
+   omitted.
   </para>
  </refsect1>
 
@@ -123,15 +131,10 @@ BEGIN;
 
   <para>
    <command>BEGIN</command> is a <productname>PostgreSQL</productname>
-   language extension.  There is no explicit <command>BEGIN</command>
-   command in the SQL standard; transaction initiation is
-   always implicit and it terminates either with a
-   <command>COMMIT</command> or <command>ROLLBACK</command> statement.
-  </para>
-
-  <para>
-   Other relational database systems may offer an autocommit feature
-   as a convenience.
+   language extension.  It is equivalent to the SQL-standard command
+   <xref linkend="sql-start-transaction"
+   endterm="sql-start-transaction-title">, which see for additional
+   compatibility information.
   </para>
 
   <para>
diff --git a/doc/src/sgml/ref/set_transaction.sgml b/doc/src/sgml/ref/set_transaction.sgml
index ef6dea1ac18e000743949b444aa4cd16b18f92bd..50a8908825078e6e2c326794a6e13a32b51c247a 100644
--- a/doc/src/sgml/ref/set_transaction.sgml
+++ b/doc/src/sgml/ref/set_transaction.sgml
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/ref/set_transaction.sgml,v 1.19 2003/11/29 19:51:39 pgsql Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/ref/set_transaction.sgml,v 1.20 2004/08/12 21:00:22 tgl Exp $ -->
 <refentry id="SQL-SET-TRANSACTION">
  <refmeta>
   <refentrytitle id="SQL-SET-TRANSACTION-TITLE">SET TRANSACTION</refentrytitle>
@@ -16,13 +16,13 @@
 
  <refsynopsisdiv>
 <synopsis>
-SET TRANSACTION
-    [ ISOLATION LEVEL { READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE } ]
-    [ READ WRITE | READ ONLY ]
+SET TRANSACTION <replaceable class="parameter">transaction_mode</replaceable> [, ...]
+SET SESSION CHARACTERISTICS AS TRANSACTION <replaceable class="parameter">transaction_mode</replaceable> [, ...]
 
-SET SESSION CHARACTERISTICS AS TRANSACTION
-    [ ISOLATION LEVEL { READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE } ]
-    [ READ WRITE | READ ONLY ]
+where <replaceable class="parameter">transaction_mode</replaceable> is one of:
+
+    ISOLATION LEVEL { SERIALIZABLE | REPEATABLE READ | READ COMMITTED | READ UNCOMMITTED }
+    READ WRITE | READ ONLY
 </synopsis>
  </refsynopsisdiv>
 
@@ -34,7 +34,7 @@ SET SESSION CHARACTERISTICS AS TRANSACTION
    characteristics of the current transaction. It has no effect on any
    subsequent transactions.  <command>SET SESSION
    CHARACTERISTICS</command> sets the default transaction
-   characteristics for each transaction of a session.  <command>SET
+   characteristics for subsequent transactions of a session.  <command>SET
    TRANSACTION</command> can override it for an individual
    transaction.
   </para>
@@ -47,7 +47,7 @@ SET SESSION CHARACTERISTICS AS TRANSACTION
 
   <para>
    The isolation level of a transaction determines what data the
-   transaction can see when other transactions are running concurrently.
+   transaction can see when other transactions are running concurrently:
 
    <variablelist>
     <varlistentry>
@@ -64,28 +64,35 @@ SET SESSION CHARACTERISTICS AS TRANSACTION
      <term><literal>SERIALIZABLE</literal></term>
      <listitem>
       <para>
-       The current transaction can only see rows committed before
-       first query or data-modification statement was executed in this transaction.
+       All statements of the current transaction can only see rows committed
+       before the first query or data-modification statement was executed in
+       this transaction.
       </para>
       <tip>
        <para>
         Intuitively, serializable means that two concurrent
         transactions will leave the database in the same state as if
-        the two has been executed strictly after one another in either
-        order.
+        the two had been executed strictly one after the other (in one
+        order or the other).
        </para>
       </tip>
      </listitem>
     </varlistentry>
    </variablelist>
 
-   The level <literal>READ UNCOMMITTED</literal> is mapped to
-   <literal>READ COMMITTED</literal>, the level <literal>REPEATABLE
-   READ</literal> is mapped to <literal>SERIALIZABLE</literal>, The
-   transaction isolation level cannot be set after the first query or
+   The SQL standard defines two additional levels, <literal>READ
+   UNCOMMITTED</literal> and <literal>REPEATABLE READ</literal>.
+   In <productname>PostgreSQL</productname> <literal>READ
+   UNCOMMITTED</literal> is treated as
+   <literal>READ COMMITTED</literal>, while <literal>REPEATABLE
+   READ</literal> is treated as <literal>SERIALIZABLE</literal>.
+  </para>
+
+  <para>
+   The transaction isolation level cannot be changed after the first query or
    data-modification statement (<command>SELECT</command>,
    <command>INSERT</command>, <command>DELETE</command>,
-   <command>UPDATE</command>, <command>FETCH</command>,
+   <command>UPDATE</command>, <command>FETCH</command>, or
    <command>COPY</command>) of a transaction has been executed.  See
    <xref linkend="mvcc"> for more information about transaction
    isolation and concurrency control.
@@ -112,13 +119,27 @@ SET SESSION CHARACTERISTICS AS TRANSACTION
   <title>Notes</title>
 
   <para>
-   The session default transaction isolation level can also be set
-   with the command
-<programlisting>
-SET default_transaction_isolation = '<replaceable>value</replaceable>'
-</programlisting>
-   and in the configuration file.  Consult <xref linkend="runtime-config"> for more
-   information.
+   If <command>SET TRANSACTION</command> is executed without a prior
+   <command>START TRANSACTION</command> or  <command>BEGIN</command>,
+   it will appear to have no effect, since the transaction will immediately
+   end.
+  </para>
+
+  <para>
+   It is possible to dispense with <command>SET TRANSACTION</command> by
+   instead specifying the desired <replaceable
+   class="parameter">transaction_modes</replaceable> in
+   <command>START TRANSACTION</command>.
+  </para>
+
+  <para>
+   The session default transaction modes can also be set by setting the
+   configuration parameters <xref linkend="guc-default-transaction-isolation">
+   and <xref linkend="guc-default-transaction-read-only">.
+   (In fact <command>SET SESSION CHARACTERISTICS</command> is just a
+   verbose equivalent for setting these variables with <command>SET</>.)
+   This allows them to be set in the configuration file.  Consult <xref
+   linkend="runtime-config"> for more information.
   </para>
  </refsect1>
 
@@ -131,7 +152,7 @@ SET default_transaction_isolation = '<replaceable>value</replaceable>'
    isolation level in the standard; in
    <productname>PostgreSQL</productname> the default is ordinarily
    <literal>READ COMMITTED</literal>, but you can change it as
-   described above.  Because of multiversion concurrency control, the
+   mentioned above.  Because of multiversion concurrency control, the
    <literal>SERIALIZABLE</literal> level is not truly
    serializable. See <xref linkend="mvcc"> for details.
   </para>
@@ -139,7 +160,15 @@ SET default_transaction_isolation = '<replaceable>value</replaceable>'
   <para>
    In the SQL standard, there is one other transaction characteristic
    that can be set with these commands: the size of the diagnostics
-   area.  This concept is only for use in embedded SQL.
+   area.  This concept is specific to embedded SQL, and therefore is
+   not implemented in the <productname>PostgreSQL</productname> server.
+  </para>
+
+  <para>
+   The SQL standard requires commas between successive <replaceable
+   class="parameter">transaction_modes</replaceable>, but for historical
+   reasons <productname>PostgreSQL</productname> allows the commas to be
+   omitted.
   </para>
  </refsect1>
 </refentry>
diff --git a/doc/src/sgml/ref/start_transaction.sgml b/doc/src/sgml/ref/start_transaction.sgml
index 1a7bc363ce7fc2ced03323dcc2dd6bb26a555f9f..823bd99195322a796d2e0062dbfdeaf6c2bc0b1f 100644
--- a/doc/src/sgml/ref/start_transaction.sgml
+++ b/doc/src/sgml/ref/start_transaction.sgml
@@ -1,5 +1,5 @@
 <!--
-$PostgreSQL: pgsql/doc/src/sgml/ref/start_transaction.sgml,v 1.12 2004/08/01 17:32:13 tgl Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/start_transaction.sgml,v 1.13 2004/08/12 21:00:23 tgl Exp $
 PostgreSQL documentation
 -->
 
@@ -20,9 +20,12 @@ PostgreSQL documentation
 
  <refsynopsisdiv>
 <synopsis>
-START TRANSACTION
-    [ ISOLATION LEVEL { READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE } ]
-    [ READ WRITE | READ ONLY ]
+START TRANSACTION [ <replaceable class="parameter">transaction_mode</replaceable> [, ...] ]
+
+where <replaceable class="parameter">transaction_mode</replaceable> is one of:
+
+    ISOLATION LEVEL { SERIALIZABLE | REPEATABLE READ | READ COMMITTED | READ UNCOMMITTED }
+    READ WRITE | READ ONLY
 </synopsis>
  </refsynopsisdiv>
 
@@ -30,10 +33,10 @@ START TRANSACTION
   <title>Description</title>
 
   <para>
-   This command begins a new transaction. If the isolation level or
+   This command begins a new transaction block. If the isolation level or
    read/write mode is specified, the new transaction has those
    characteristics, as if <xref linkend="sql-set-transaction"
-   endterm="sql-set-transaction-title"> was executed. It is the same
+   endterm="sql-set-transaction-title"> was executed. This is the same
    as the <xref linkend="sql-begin" endterm="sql-begin-title"> command.
   </para>
  </refsect1>
@@ -52,8 +55,25 @@ START TRANSACTION
   <title>Compatibility</title>
 
   <para>
-   This command conforms to the SQL standard; but see also the
-   compatibility section of <xref linkend="sql-set-transaction"
+   In the standard, it is not necessary to issue <command>START TRANSACTION</>
+   to start a transaction block: any SQL command implicitly begins a block.
+   <productname>PostgreSQL</productname>'s behavior can be seen as implicitly
+   issuing a <command>COMMIT</command> after each command that does not
+   follow <command>START TRANSACTION</> (or <command>BEGIN</command>),
+   and it is therefore often called <quote>autocommit</>.
+   Other relational database systems may offer an autocommit feature
+   as a convenience.
+  </para>
+
+  <para>
+   The SQL standard requires commas between successive <replaceable
+   class="parameter">transaction_modes</replaceable>, but for historical
+   reasons <productname>PostgreSQL</productname> allows the commas to be
+   omitted.
+  </para>
+
+  <para>
+   See also the compatibility section of <xref linkend="sql-set-transaction"
    endterm="sql-set-transaction-title">.
   </para>
  </refsect1>
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 6a27714b05e5ad7a8f12b2d2b80a19762afe5ef8..e8bc3cf5adec80667e41f483e87b842de672e872 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -11,7 +11,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.470 2004/08/12 19:12:21 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.471 2004/08/12 21:00:28 tgl Exp $
  *
  * HISTORY
  *	  AUTHOR			DATE			MAJOR EVENT
@@ -161,11 +161,11 @@ static void doNegateFloat(Value *v);
 
 %type <dbehavior>	opt_drop_behavior
 
-%type <list>	createdb_opt_list copy_opt_list
-%type <defelt>	createdb_opt_item copy_opt_item
+%type <list>	createdb_opt_list copy_opt_list transaction_mode_list
+%type <defelt>	createdb_opt_item copy_opt_item transaction_mode_item
 
 %type <ival>	opt_lock lock_type cast_context
-%type <boolean>	opt_force opt_or_replace transaction_access_mode
+%type <boolean>	opt_force opt_or_replace
 				opt_grant_grant_option opt_revoke_grant_option
 				opt_nowait
 
@@ -222,7 +222,7 @@ static void doNegateFloat(Value *v);
 				target_list update_target_list insert_column_list
 				insert_target_list def_list indirection opt_indirection
 				group_clause TriggerFuncArgs select_limit
-				opt_select_limit opclass_item_list transaction_mode_list
+				opt_select_limit opclass_item_list
 				transaction_mode_list_or_empty
 				TableFuncElementList
 				prep_type_clause prep_type_list
@@ -4021,27 +4021,26 @@ opt_transaction:	WORK							{}
 			| /*EMPTY*/								{}
 		;
 
-transaction_mode_list:
+transaction_mode_item:
 			ISOLATION LEVEL iso_level
-					{ $$ = list_make1(makeDefElem("transaction_isolation",
-												  makeStringConst($3, NULL))); }
-			| transaction_access_mode
-					{ $$ = list_make1(makeDefElem("transaction_read_only",
-												  makeIntConst($1))); }
-			| ISOLATION LEVEL iso_level transaction_access_mode
-					{
-						$$ = list_make2(makeDefElem("transaction_isolation",
-													makeStringConst($3, NULL)),
-										makeDefElem("transaction_read_only",
-													makeIntConst($4)));
-					}
-			| transaction_access_mode ISOLATION LEVEL iso_level
-					{
-						$$ = list_make2(makeDefElem("transaction_read_only",
-													makeIntConst($1)),
-										makeDefElem("transaction_isolation",
-													makeStringConst($4, NULL)));
-					}
+					{ $$ = makeDefElem("transaction_isolation",
+									   makeStringConst($3, NULL)); }
+			| READ ONLY
+					{ $$ = makeDefElem("transaction_read_only",
+									   makeIntConst(TRUE)); }
+			| READ WRITE
+					{ $$ = makeDefElem("transaction_read_only",
+									   makeIntConst(FALSE)); }
+		;
+
+/* Syntax with commas is SQL-spec, without commas is Postgres historical */
+transaction_mode_list:
+			transaction_mode_item
+					{ $$ = list_make1($1); }
+			| transaction_mode_list ',' transaction_mode_item
+					{ $$ = lappend($1, $3); }
+			| transaction_mode_list transaction_mode_item
+					{ $$ = lappend($1, $2); }
 		;
 
 transaction_mode_list_or_empty:
@@ -4050,11 +4049,6 @@ transaction_mode_list_or_empty:
 					{ $$ = NIL; }
 		;
 
-transaction_access_mode:
-			READ ONLY { $$ = TRUE; }
-			| READ WRITE { $$ = FALSE; }
-		;
-
 
 /*****************************************************************************
  *
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index 89ac4843ba8ba99d5e48740f3de8edae04d840bd..0fff253a61c5fede4c42cdf313e72df3a8274455 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/tcop/utility.c,v 1.224 2004/08/12 19:12:21 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/tcop/utility.c,v 1.225 2004/08/12 21:00:34 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -333,23 +333,21 @@ ProcessUtility(Node *parsetree,
 					case TRANS_STMT_BEGIN:
 					case TRANS_STMT_START:
 						{
-							BeginTransactionBlock();
+							ListCell   *lc;
 
-							if (stmt->options)
+							BeginTransactionBlock();
+							foreach(lc, stmt->options)
 							{
-								ListCell   *head;
-
-								foreach(head, stmt->options)
-								{
-									DefElem    *item = (DefElem *) lfirst(head);
-
-									if (strcmp(item->defname, "transaction_isolation") == 0)
-										SetPGVariable("transaction_isolation",
-											list_make1(item->arg), false);
-									else if (strcmp(item->defname, "transaction_read_only") == 0)
-										SetPGVariable("transaction_read_only",
-											list_make1(item->arg), false);
-								}
+								DefElem    *item = (DefElem *) lfirst(lc);
+
+								if (strcmp(item->defname, "transaction_isolation") == 0)
+									SetPGVariable("transaction_isolation",
+												  list_make1(item->arg),
+												  false);
+								else if (strcmp(item->defname, "transaction_read_only") == 0)
+									SetPGVariable("transaction_read_only",
+												  list_make1(item->arg),
+												  false);
 							}
 						}
 						break;