Skip to content

Commit c6d7e61

Browse files
committed
Add ATX documentation
1 parent 9bc553c commit c6d7e61

File tree

7 files changed

+233
-169
lines changed

7 files changed

+233
-169
lines changed

doc/src/sgml/atx.sgml

Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
<!-- doc/src/sgml/atx.sgml -->
2+
3+
<chapter id="atx">
4+
<title>Autonomous transactions.</title>
5+
6+
<sect1 id="atx-overview">
7+
<title>Overview of autonomous transactions</title>
8+
9+
<para>
10+
Postgres supports nested transactions: them are rarely explicitly used by programmer and mostly used for error handling and stored
11+
procedures. It is possible to rollback subtransaction without affecting parent transaction. But commit of subtraction is delayed until
12+
commit of parent transaction.
13+
</para>
14+
<para>
15+
But in some cases application needs to run several independent transactions in one session.
16+
"Autonomous Subtransactions" (in short AST) denotes the capability of a single session to run multiple independent transactions, as if multiple different sessions were executing each transaction.
17+
</para>
18+
<para>
19+
Autonomous transactions are needed mostly for implementing audits, when the fact of performing audit should be reported regardless
20+
status of audit itself: whether it was successfully completed or not.
21+
Autonomous transactions are widely used in Oracle PL-SQL, at porting such procedures to Postgres is problematic without autonomous transaction support.
22+
</para>
23+
24+
</sect1>
25+
26+
<sect1 id="behaviour"><title>Behavior</title>
27+
<para>
28+
An AST can happen only inside another transaction.
29+
Inside an existing transaction (call it T0), the user can decide to start a subtransaction. Then T0 is paused and pushed in an AST stack, and a new transaction (call it T1) is started.
30+
</para>
31+
<para>
32+
At some point in the future the user can commit the subtransaction; after T1 is committed then T0 is popped from the AST stack and resumed.
33+
The user can also decide to COMMIT the parent transaction T0, in which case T1 is committed, then T0 is popped from the AST stack and then committed.
34+
</para>
35+
<para>
36+
All the transactions happen synchronously; at any time only one transaction can be active, while in the stack there are zero (or more) paused transactions in the stack.
37+
All the possible combinations of COMMIT / ROLLBACK for T0 and T1 can happen; for instance, it is possible to COMMIT T1 and ROLLBACK T0.
38+
It is possible to nest subtransactions, up to a global resource limit (e.g. the AST stack size) which can be set on the server.
39+
</para>
40+
41+
</sect1>
42+
43+
<sect1 id="example"><title>Example</title>
44+
45+
<para>
46+
The following figure describes an example where a transaction executes a subtransaction. A continuous line denotes an active transaction, while a dotted line denotes a transaction which has been paused and pushed in the AST stack. Time flows downwards.
47+
48+
<programlisting>
49+
BEGIN; -- start ordinary tx T0
50+
|
51+
INSERT INTO t VALUES (1);
52+
:\
53+
: BEGIN AUTONOMOUS SUBTRANSACTION; -- start AST tx T1, pushes T0 into stack
54+
: |
55+
: INSERT INTO t VALUES (2);
56+
: |
57+
: COMMIT AUTONOMOUS TRANSACTION / ROLLBACK AUTONOMOUS TRANSACTION; -- ends tx T1, pops tx T0 from stack
58+
:/
59+
COMMIT / ROLLBACK; -- ends tx T0
60+
</programlisting>
61+
62+
<para>
63+
Depending on the two choices between COMMIT and ROLLBACK we can get 4 different outputs from
64+
</para>
65+
66+
<programlisting>
67+
SELECT sum(x) from t;
68+
</programlisting>
69+
70+
</sect1>
71+
<sect1 id="example2"><title>Example 2 (more than one subtransaction)</title>
72+
73+
<para>
74+
The parent transaction can have more than one subtransaction, just by repeating the application of the push/pop cycle.
75+
</para>
76+
77+
<programlisting>
78+
BEGIN; -- start ordinary tx T0
79+
|
80+
INSERT INTO t VALUES (1);
81+
:\
82+
: BEGIN AUTONOMOUS TRANSACTION; -- start AST tx T1, pushes T0 into stack
83+
: |
84+
: INSERT INTO t VALUES (2);
85+
: |
86+
: COMMIT AUTONOMOUS TRANSACTION / ROLLBACK AUTONOMOUS TRANSACTION; -- ends tx T1, pops tx T0 from stack
87+
:/
88+
|
89+
:\
90+
: BEGIN AUTONOMOUS TRANSACTION; -- start AST tx T2, pushes T0 into stack
91+
: |
92+
: INSERT INTO t VALUES (4);
93+
: |
94+
: COMMIT AUTONOMOUS TRANSACTION / ROLLBACK AUTONOMOUS TRANSACTION; -- ends tx T2, pops tx T0 from stack
95+
:/
96+
COMMIT / ROLLBACK; -- ends tx T0
97+
</programlisting>
98+
99+
</sect1>
100+
101+
<sect1 id="visibility"><title>Visibility</title>
102+
103+
<para>
104+
Visibility rules work as in the case of independent transactions executed via dblink. T1 does not see the effects of T0, because the latter has not been committed yet. T0 might see the effects of T1, depending on its own transaction isolation mode.
105+
In case of read committed isolation level parent transaction will see changes made by autonomous subtransaction.
106+
But in case of repeatable read isolation level parent transaction will not see changes made by autonomous subtransaction.
107+
</para>
108+
109+
<para>
110+
Now single-session deadlocks become possible, because an AST can become entangled with one of the paused transactions in its session.
111+
Autonomous transaction T1 is assumed to depend on parent transaction T1 and if it attempt to obtain any resource locked by T0, then
112+
deadlock is reported.
113+
</para>
114+
115+
</sect1>
116+
117+
<sect1 id="sql-grammar"><title>SQL grammar extension for autonomous transactions</title>
118+
119+
<para>
120+
Postgres <literal>BEGIN</literal>/<literal>END</literal> transaction statements are extended by by optional keyword <literal>autonomous</literal>:
121+
</para>
122+
123+
<programlisting>
124+
BEGIN [AUTONOMOUS] [TRANSACTION] [isolation-level]
125+
END [AUTONOMOUS] [TRANSACTION]
126+
</programlisting>
127+
128+
<para>
129+
Specifying autonomous keyword in end transaction clause is optional.
130+
It is possible to have several nesting levels of autonomous transactions, but top level transaction can not be autonomous.
131+
</para>
132+
133+
</sect1>
134+
135+
<sect1 id="plpgsql-grammar"><title>PL/pgSQL grammar extension for autonomous transactions</title>
136+
137+
<para>
138+
Block construction in PL/pgSQL is extended by optional autonomous keyword.
139+
It is possible to treat all function body as autonomous transaction:
140+
</para>
141+
142+
<programlisting>
143+
create function foo(x integer) returns integer as $$
144+
begin autonomous
145+
return x;
146+
end;
147+
$$ language plpgsql;
148+
</programlisting>
149+
150+
<para>
151+
or create separate begin-end block:
152+
</para>
153+
154+
<programlisting>
155+
create or replace function myaudit() returns boolean as $$
156+
begin autonomous
157+
begin autonomous
158+
insert into audit_schedule values ('new audit',now());
159+
end;
160+
... -- do audit itself
161+
return true;
162+
end;
163+
$$ language plpgsql;
164+
</programlisting>
165+
166+
<para>
167+
When exception is raised inside BEGIN AUTONOMOUS block, this autonomous transaction is aborted and standard
168+
exception handling procedure is started, unwinding stack and executing exception handlers until exception is caught.
169+
So exception handling is done i the same way as with normal Postgres subtransactions.
170+
</para>
171+
<para>
172+
When an error is caught by an EXCEPTION clause, the local variables of the PL/pgSQL function remain as they were when the error occurred, but all changes to persistent database state within the block are rolled back.
173+
</para>
174+
175+
</sect1>
176+
177+
<sect1 id="plpython-grammar"><title>PL/python extension for autonomous transactions</title>
178+
179+
<para>
180+
In addition to <varname>subtransaction</varname> method, Plpython module provides new <varname>autonomous</varname> method
181+
which can be used in <varname>>WITH</varname> clause to start autonomous transaction:
182+
</para>
183+
184+
<programlisting>
185+
create or replace function pythonomous() returns void as $$
186+
plpy.execute("insert into atx_test values ('asd', 123)")
187+
188+
try:
189+
with plpy.autonomous():
190+
plpy.execute("insert into atx_test values ('bsd', 456)")
191+
except plpy.SPIError, e:
192+
print("error: %s" % e.args)
193+
194+
plpy.execute("insert into atx_test values ('csd', 'csd')")
195+
$$ language plpythonu;
196+
</programlisting>
197+
198+
<para>
199+
Exception handling for autonomous transaction in plpython is done in the same way as for subtransactions.
200+
</para>
201+
202+
</sect1>
203+
</chapter>

doc/src/sgml/filelist.sgml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
<!ENTITY syntax SYSTEM "syntax.sgml">
3333
<!ENTITY textsearch SYSTEM "textsearch.sgml">
3434
<!ENTITY typeconv SYSTEM "typeconv.sgml">
35+
<!ENTITY atx SYSTEM "atx.sgml">
3536

3637
<!-- administrator's guide -->
3738
<!ENTITY backup SYSTEM "backup.sgml">

doc/src/sgml/keywords.sgml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,13 @@
356356
<entry>reserved</entry>
357357
<entry>reserved</entry>
358358
</row>
359+
<row>
360+
<entry><token>AUTONOMOUS</token></entry>
361+
<entry>non-reserved</entry>
362+
<entry>reserved</entry>
363+
<entry>reserved</entry>
364+
<entry>reserved</entry>
365+
</row>
359366
<row>
360367
<entry><token>AVG</token></entry>
361368
<entry></entry>

doc/src/sgml/postgres.sgml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@
108108
&mvcc;
109109
&perform;
110110
&parallel;
111+
&atx;
111112

112113
</part>
113114

doc/src/sgml/ref/begin.sgml

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ doc/src/sgml/ref/begin.sgml
2121

2222
<refsynopsisdiv>
2323
<synopsis>
24-
BEGIN [ WORK | TRANSACTION ] [ <replaceable class="parameter">transaction_mode</replaceable> [, ...] ]
24+
BEGIN [ AUTONOMOUS ] [ WORK | TRANSACTION ] [ <replaceable class="parameter">transaction_mode</replaceable> [, ...] ]
2525

2626
<phrase>where <replaceable class="parameter">transaction_mode</replaceable> is one of:</phrase>
2727

@@ -63,6 +63,13 @@ BEGIN [ WORK | TRANSACTION ] [ <replaceable class="parameter">transaction_mode</
6363
<xref linkend="sql-set-transaction">
6464
was executed.
6565
</para>
66+
67+
<para>
68+
In case of presence of optional <command>AUTONOMOUS</command> keyword, autonomous transaction is started.
69+
Autonomous transaction can be started only within some other transaction.
70+
See section <xref linkend="atx"> for more details about autonomous transactions.
71+
</para>
72+
6673
</refsect1>
6774

6875
<refsect1>
@@ -78,6 +85,17 @@ BEGIN [ WORK | TRANSACTION ] [ <replaceable class="parameter">transaction_mode</
7885
</para>
7986
</listitem>
8087
</varlistentry>
88+
89+
<varlistentry>
90+
<term><literal>AUTONOMOUS</literal></term>
91+
<listitem>
92+
<para>
93+
Optional key words. Cause start of autonomous subtransaction.
94+
Autonomous transaction can be started only within some other transaction.
95+
See section <xref linkend="atx"> for more details about autonomous transactions.
96+
</para>
97+
</listitem>
98+
</varlistentry>
8199
</variablelist>
82100

83101
<para>

doc/src/sgml/ref/end.sgml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ doc/src/sgml/ref/end.sgml
2121

2222
<refsynopsisdiv>
2323
<synopsis>
24-
END [ WORK | TRANSACTION ]
24+
END [ AUTONOMOUS ] [ WORK | TRANSACTION ]
2525
</synopsis>
2626
</refsynopsisdiv>
2727

@@ -44,6 +44,7 @@ END [ WORK | TRANSACTION ]
4444
<varlistentry>
4545
<term><literal>WORK</literal></term>
4646
<term><literal>TRANSACTION</literal></term>
47+
<term><literal>AUTONOMOUS</literal></term>
4748
<listitem>
4849
<para>
4950
Optional key words. They have no effect.

0 commit comments

Comments
 (0)