diff options
-rw-r--r-- | doc/src/sgml/catalogs.sgml | 7 | ||||
-rw-r--r-- | doc/src/sgml/config.sgml | 6 | ||||
-rw-r--r-- | doc/src/sgml/filelist.sgml | 1 | ||||
-rw-r--r-- | doc/src/sgml/monitoring.sgml | 3 | ||||
-rw-r--r-- | doc/src/sgml/pgrowlocks.sgml | 3 | ||||
-rw-r--r-- | doc/src/sgml/postgres.sgml | 1 | ||||
-rw-r--r-- | doc/src/sgml/ref/release_savepoint.sgml | 62 | ||||
-rw-r--r-- | doc/src/sgml/ref/rollback.sgml | 8 | ||||
-rw-r--r-- | doc/src/sgml/ref/rollback_to.sgml | 5 | ||||
-rw-r--r-- | doc/src/sgml/wal.sgml | 6 | ||||
-rw-r--r-- | doc/src/sgml/xact.sgml | 200 |
11 files changed, 266 insertions, 36 deletions
diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml index 3f8508060d9..a80ed029ba3 100644 --- a/doc/src/sgml/catalogs.sgml +++ b/doc/src/sgml/catalogs.sgml @@ -9187,7 +9187,8 @@ SCRAM-SHA-256$<replaceable><iteration count></replaceable>:<replaceable>&l <entry></entry> <entry> Virtual ID of the transaction targeted by the lock, - or null if the target is not a virtual transaction ID + or null if the target is not a virtual transaction ID; see + <xref linkend="transactions"/> </entry> </row> <row> @@ -9195,8 +9196,8 @@ SCRAM-SHA-256$<replaceable><iteration count></replaceable>:<replaceable>&l <entry><type>xid</type></entry> <entry></entry> <entry> - ID of the transaction targeted by the lock, - or null if the target is not a transaction ID + ID of the transaction targeted by the lock, or null if the target + is not a transaction ID; <xref linkend="transactions"/> </entry> </row> <row> diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml index 46b044de903..94484c3bca4 100644 --- a/doc/src/sgml/config.sgml +++ b/doc/src/sgml/config.sgml @@ -6566,12 +6566,14 @@ local0.* /var/log/postgresql </row> <row> <entry><literal>%v</literal></entry> - <entry>Virtual transaction ID (backendID/localXID)</entry> + <entry>Virtual transaction ID (backendID/localXID); see + <xref linkend="transaction-id"/></entry> <entry>no</entry> </row> <row> <entry><literal>%x</literal></entry> - <entry>Transaction ID (0 if none is assigned)</entry> + <entry>Transaction ID (0 if none is assigned); see + <xref linkend="transaction-id"/></entry> <entry>no</entry> </row> <row> diff --git a/doc/src/sgml/filelist.sgml b/doc/src/sgml/filelist.sgml index a58494720f8..d752c48dda2 100644 --- a/doc/src/sgml/filelist.sgml +++ b/doc/src/sgml/filelist.sgml @@ -101,6 +101,7 @@ <!ENTITY protocol SYSTEM "protocol.sgml"> <!ENTITY sources SYSTEM "sources.sgml"> <!ENTITY storage SYSTEM "storage.sgml"> +<!ENTITY transaction SYSTEM "xact.sgml"> <!ENTITY tablesample-method SYSTEM "tablesample-method.sgml"> <!ENTITY generic-wal SYSTEM "generic-wal.sgml"> diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml index b2a27c8c7fc..dd72c16bebf 100644 --- a/doc/src/sgml/monitoring.sgml +++ b/doc/src/sgml/monitoring.sgml @@ -817,7 +817,8 @@ postgres 27093 0.0 0.0 30096 2752 ? Ss 11:34 0:00 postgres: ser <row> <entry><structfield>backend_xid</structfield></entry> <entry><type>xid</type></entry> - <entry>Top-level transaction identifier of this backend, if any.</entry> + <entry>Top-level transaction identifier of this backend, if any; see + <xref linkend="transaction-id"/>.</entry> </row> <row> <entry><structfield>backend_xmin</structfield></entry> diff --git a/doc/src/sgml/pgrowlocks.sgml b/doc/src/sgml/pgrowlocks.sgml index 392d5f1f9a7..02f31601b06 100644 --- a/doc/src/sgml/pgrowlocks.sgml +++ b/doc/src/sgml/pgrowlocks.sgml @@ -57,7 +57,8 @@ pgrowlocks(text) returns setof record <row> <entry><structfield>locker</structfield></entry> <entry><type>xid</type></entry> - <entry>Transaction ID of locker, or multixact ID if multitransaction</entry> + <entry>Transaction ID of locker, or multixact ID if + multitransaction; see <xref linkend="transaction-id"/></entry> </row> <row> <entry><structfield>multi</structfield></entry> diff --git a/doc/src/sgml/postgres.sgml b/doc/src/sgml/postgres.sgml index 405e1c7b085..61811457167 100644 --- a/doc/src/sgml/postgres.sgml +++ b/doc/src/sgml/postgres.sgml @@ -260,6 +260,7 @@ &brin; &hash; &storage; + &transaction; &bki; &planstats; diff --git a/doc/src/sgml/ref/release_savepoint.sgml b/doc/src/sgml/ref/release_savepoint.sgml index daf8eb9a436..e9fc6e5d1c8 100644 --- a/doc/src/sgml/ref/release_savepoint.sgml +++ b/doc/src/sgml/ref/release_savepoint.sgml @@ -21,7 +21,7 @@ PostgreSQL documentation <refnamediv> <refname>RELEASE SAVEPOINT</refname> - <refpurpose>destroy a previously defined savepoint</refpurpose> + <refpurpose>release a previously defined savepoint</refpurpose> </refnamediv> <refsynopsisdiv> @@ -34,23 +34,13 @@ RELEASE [ SAVEPOINT ] <replaceable>savepoint_name</replaceable> <title>Description</title> <para> - <command>RELEASE SAVEPOINT</command> destroys a savepoint previously defined - in the current transaction. - </para> - - <para> - Destroying a savepoint makes it unavailable as a rollback point, - but it has no other user visible behavior. It does not undo the - effects of commands executed after the savepoint was established. - (To do that, see <xref linkend="sql-rollback-to"/>.) - Destroying a savepoint when - it is no longer needed allows the system to reclaim some resources - earlier than transaction end. - </para> - - <para> - <command>RELEASE SAVEPOINT</command> also destroys all savepoints that were - established after the named savepoint was established. + <command>RELEASE SAVEPOINT</command> releases the named savepoint and + all active savepoints that were created after the named savepoint, + and frees their resources. All changes made since the creation of + the savepoint that didn't already get rolled back are merged into + the transaction or savepoint that was active when the named savepoint + was created. Changes made after <command>RELEASE SAVEPOINT</command> + will also be part of this active transaction or savepoint. </para> </refsect1> @@ -62,7 +52,7 @@ RELEASE [ SAVEPOINT ] <replaceable>savepoint_name</replaceable> <term><replaceable>savepoint_name</replaceable></term> <listitem> <para> - The name of the savepoint to destroy. + The name of the savepoint to release. </para> </listitem> </varlistentry> @@ -78,7 +68,7 @@ RELEASE [ SAVEPOINT ] <replaceable>savepoint_name</replaceable> <para> It is not possible to release a savepoint when the transaction is in - an aborted state. + an aborted state; to do that, use <xref linkend="sql-rollback-to"/>. </para> <para> @@ -93,7 +83,7 @@ RELEASE [ SAVEPOINT ] <replaceable>savepoint_name</replaceable> <title>Examples</title> <para> - To establish and later destroy a savepoint: + To establish and later release a savepoint: <programlisting> BEGIN; INSERT INTO table1 VALUES (3); @@ -104,6 +94,36 @@ COMMIT; </programlisting> The above transaction will insert both 3 and 4. </para> + + <para> + A more complex example with multiple nested subtransactions: +<programlisting> +BEGIN; + INSERT INTO table1 VALUES (1); + SAVEPOINT sp1; + INSERT INTO table1 VALUES (2); + SAVEPOINT sp2; + INSERT INTO table1 VALUES (3); + RELEASE SAVEPOINT sp2; + INSERT INTO table1 VALUES (4))); -- generates an error +</programlisting> + In this example, the application requests the release of the savepoint + <literal>sp2</literal>, which inserted 3. This changes the insert's + transaction context to <literal>sp1</literal>. When the statement + attempting to insert value 4 generates an error, the insertion of 2 and + 4 are lost because they are in the same, now-rolled back savepoint, + and value 3 is in the same transaction context. The application can + now only choose one of these two commands, since all other commands + will be ignored: +<programlisting> + ROLLBACK; + ROLLBACK TO SAVEPOINT sp1; +</programlisting> + Choosing <command>ROLLBACK</command> will abort everything, including + value 1, whereas <command>ROLLBACK TO SAVEPOINT sp1</command> will retain + value 1 and allow the transaction to continue. + </para> + </refsect1> <refsect1> diff --git a/doc/src/sgml/ref/rollback.sgml b/doc/src/sgml/ref/rollback.sgml index 1357eaa8323..7f8a088c7fe 100644 --- a/doc/src/sgml/ref/rollback.sgml +++ b/doc/src/sgml/ref/rollback.sgml @@ -56,10 +56,10 @@ ROLLBACK [ WORK | TRANSACTION ] [ AND [ NO ] CHAIN ] <term><literal>AND CHAIN</literal></term> <listitem> <para> - If <literal>AND CHAIN</literal> is specified, a new transaction is - immediately started with the same transaction characteristics (see <xref - linkend="sql-set-transaction"/>) as the just finished one. Otherwise, - no new transaction is started. + If <literal>AND CHAIN</literal> is specified, a new (not aborted) + transaction is immediately started with the same transaction + characteristics (see <xref linkend="sql-set-transaction"/>) as the + just finished one. Otherwise, no new transaction is started. </para> </listitem> </varlistentry> diff --git a/doc/src/sgml/ref/rollback_to.sgml b/doc/src/sgml/ref/rollback_to.sgml index 4d5647a302e..827235eec29 100644 --- a/doc/src/sgml/ref/rollback_to.sgml +++ b/doc/src/sgml/ref/rollback_to.sgml @@ -35,8 +35,9 @@ ROLLBACK [ WORK | TRANSACTION ] TO [ SAVEPOINT ] <replaceable>savepoint_name</re <para> Roll back all commands that were executed after the savepoint was - established. The savepoint remains valid and can be rolled back to - again later, if needed. + established and then start a new subtransaction at the same transaction level. + The savepoint remains valid and can be rolled back to again later, + if needed. </para> <para> diff --git a/doc/src/sgml/wal.sgml b/doc/src/sgml/wal.sgml index a94edf4d8b6..bd7886187df 100644 --- a/doc/src/sgml/wal.sgml +++ b/doc/src/sgml/wal.sgml @@ -4,8 +4,9 @@ <title>Reliability and the Write-Ahead Log</title> <para> - This chapter explains how the Write-Ahead Log is used to obtain - efficient, reliable operation. + This chapter explains how to control the reliability of + <productname>PostgreSQL</productname>, including details about the + Write-Ahead Log. </para> <sect1 id="wal-reliability"> @@ -811,4 +812,5 @@ seem to be a problem in practice. </para> </sect1> + </chapter> diff --git a/doc/src/sgml/xact.sgml b/doc/src/sgml/xact.sgml new file mode 100644 index 00000000000..da3ab662870 --- /dev/null +++ b/doc/src/sgml/xact.sgml @@ -0,0 +1,200 @@ +<!-- doc/src/sgml/mvcc.sgml --> + +<chapter id="transactions"> + + <title>Transaction Processing</title> + + <para> + This chapter provides an overview of the internals of + <productname>PostgreSQL</productname>'s transaction management system. + The word transaction is often abbreviated as <firstterm>xact</firstterm>. + </para> + + <sect1 id="transaction-id"> + + <title>Transactions and Identifiers</title> + + <para> + Transactions can be created explicitly using <command>BEGIN</command> + or <command>START TRANSACTION</command> and ended using + <command>COMMIT</command> or <command>ROLLBACK</command>. SQL + statements outside of explicit transactions automatically use + single-statement transactions. + </para> + + <para> + Every transaction is identified by a unique + <literal>VirtualTransactionId</literal> (also called + <literal>virtualXID</literal> or <literal>vxid</literal>), which + is comprised of a backend ID (or <literal>backendID</literal>) + and a sequentially-assigned number local to each backend, known as + <literal>localXID</literal>. For example, the virtual transaction + ID <literal>4/12532</literal> has a <literal>backendID</literal> + of <literal>4</literal> and a <literal>localXID</literal> of + <literal>12532</literal>. + </para> + + <para> + Non-virtual <literal>TransactionId</literal>s (or <type>xid</type>), + e.g., <literal>278394</literal>, are assigned sequentially to + transactions from a global counter used by all databases within + the <productname>PostgreSQL</productname> cluster. This assignment + happens when a transaction first writes to the database. This means + lower-numbered xids started writing before higher-numbered xids. + Note that the order in which transactions perform their first database + write might be different from the order in which the transactions + started, particularly if the transaction started with statements that + only performed database reads. + </para> + + <para> + The internal transaction ID type <type>xid</type> is 32 bits wide + and <link linkend="vacuum-for-wraparound">wraps around</link> every + 4 billion transactions. A 32-bit epoch is incremented during each + wraparound. Xids are used as the basis for + <productname>PostgreSQL</productname>'s <link linkend="mvcc">MVCC</link> + concurrency mechanism and streaming replication. + </para> + + <para> + When a top-level transaction with a (non-virtual) xid commits, + it is marked as committed in the <filename>pg_xact</filename> + directory. Additional information is recorded in the + <filename>pg_commit_ts</filename> directory if <xref + linkend="guc-track-commit-timestamp"/> is enabled. + </para> + + <para> + In addition to <literal>vxid</literal> and <type>xid</type>, + prepared transactions are also assigned Global Transaction + Identifiers (<acronym>GID</acronym>). GIDs are string literals up + to 200 bytes long, which must be unique amongst other currently + prepared transactions. The mapping of GID to xid is shown in <link + linkend="view-pg-prepared-xacts"><structname>pg_prepared_xacts</structname></link>. + </para> + </sect1> + + <sect1 id="xact-locking"> + + <title>Transactions and Locking</title> + + <para> + The transaction IDs of currently executing transactions are shown in + <link linkend="view-pg-locks"><structname>pg_locks</structname></link> + in columns <structfield>virtualxid</structfield> and + <structfield>transactionid</structfield>. Read-only transactions + will have <structfield>virtualxid</structfield>s but NULL + <structfield>transactionid</structfield>s, while both columns will be + set in read-write transactions. + </para> + + <para> + Some lock types wait on <structfield>virtualxid</structfield>, + while other types wait on <structfield>transactionid</structfield>. + Row-level read and write locks are recorded directly in the locked + rows and can be inspected using the <xref linkend="pgrowlocks"/> + extension. Row-level read locks might also require the assignment + of multixact IDs (<literal>mxid</literal>; see <xref + linkend="vacuum-for-multixact-wraparound"/>). + </para> + </sect1> + + <sect1 id="subxacts"> + + <title>Subtransactions</title> + + <para> + Subtransactions are started inside transactions, allowing large + transactions to be broken into smaller units. Subtransactions can + commit or abort without affecting their parent transactions, allowing + parent transactions to continue. This allows errors to be handled + more easily, which is a common application development pattern. + The word subtransaction is often abbreviated as + <firstterm>subxact</firstterm>. + </para> + + <para> + Subtransactions can be started explicitly using the + <command>SAVEPOINT</command> command, but can also be started in + other ways, such as PL/pgSQL's <command>EXCEPTION</command> clause. + PL/Python and PL/TCL also support explicit subtransactions. + Subtransactions can also be started from other subtransactions. + The top-level transaction and its child subtransactions form a + hierarchy or tree, which is why we refer to the main transaction as + the top-level transaction. + </para> + + <para> + If a subtransaction is assigned a non-virtual transaction ID, + its transaction ID is referred to as a <quote>subxid</quote>. + Read-only subtransactions are not assigned subxids, but once they + attempt to write, they will be assigned one. This also causes all of + a subxid's parents, up to and including the top-level transaction, + to be assigned non-virtual transaction ids. We ensure that a parent + xid is always lower than any of its child subxids. + </para> + + <para> + The immediate parent xid of each subxid is recorded in the + <filename>pg_subtrans</filename> directory. No entry is made for + top-level xids since they do not have a parent, nor is an entry made + for read-only subtransactions. + </para> + + <para> + When a subtransaction commits, all of its committed child + subtransactions with subxids will also be considered subcommitted + in that transaction. When a subtransaction aborts, all of its child + subtransactions will also be considered aborted. + </para> + + <para> + When a top-level transaction with an xid commits, all of its + subcommitted child subtransactions are also persistently recorded + as committed in the <filename>pg_xact</filename> directory. If the + top-level transaction aborts, all its subtransactions are also aborted, + even if they were subcommitted. + </para> + + <para> + The more subtransactions each transaction keeps open (not + rolled back or released), the greater the transaction management + overhead. Up to 64 open subxids are cached in shared memory for + each backend; after that point, the storage I/O overhead increases + significantly due to additional lookups of subxid entries in + <filename>pg_subtrans</filename>. + </para> + </sect1> + + <sect1 id="two-phase"> + + <title>Two-Phase Transactions</title> + + <para> + <productname>PostgreSQL</productname> supports a two-phase commit (2PC) + protocol that allows multiple distributed systems to work together + in a transactional manner. The commands are <command>PREPARE + TRANSACTION</command>, <command>COMMIT PREPARED</command> and + <command>ROLLBACK PREPARED</command>. Two-phase transactions + are intended for use by external transaction management systems. + <productname>PostgreSQL</productname> follows the features and model + proposed by the X/Open XA standard, but does not implement some less + often used aspects. + </para> + + <para> + When the user executes <command>PREPARE TRANSACTION</command>, the + only possible next commands are <command>COMMIT PREPARED</command> + or <command>ROLLBACK PREPARED</command>. In general, this prepared + state is intended to be of very short duration, but external + availability issues might mean transactions stay in this state + for an extended interval. Short-lived prepared + transactions are stored only in shared memory and WAL. + Transactions that span checkpoints are recorded in the + <filename>pg_twophase</filename> directory. Transactions + that are currently prepared can be inspected using <link + linkend="view-pg-prepared-xacts"><structname>pg_prepared_xacts</structname></link>. + </para> + </sect1> + +</chapter> |