<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Blog @ SIB Visions &#187; PostgreSQL</title>
	<atom:link href="http://blog.sibvisions.com/tag/postgresql/feed/" rel="self" type="application/rss+xml" />
	<link>https://blog.sibvisions.com</link>
	<description>Blog @ SIB Visions</description>
	<lastBuildDate>Fri, 10 Apr 2026 10:13:07 +0000</lastBuildDate>
		<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>JVx and PostgreSQL, supporting Savepoints</title>
		<link>https://blog.sibvisions.com/2018/02/12/jvx-postgresql-savepoints/</link>
		<comments>https://blog.sibvisions.com/2018/02/12/jvx-postgresql-savepoints/#comments</comments>
		<pubDate>Mon, 12 Feb 2018 10:05:51 +0000</pubDate>
		<dc:creator>rzenz</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Information]]></category>
		<category><![CDATA[JDBC]]></category>
		<category><![CDATA[JVx]]></category>
		<category><![CDATA[PostgreSQL]]></category>

		<guid isPermaLink="false">https://blog.sibvisions.com/?p=7704</guid>
		<description><![CDATA[Transactions are an integral mechanism of databases, without them we could hardly ensure data consistency. Well, we could of course, but it would be a lot more work. JDBC has of course support for transactions, but it also supports so called "Savepoints", which we will have a look at today.
What are transactions?
Normally, I'd assume that [...]]]></description>
			<content:encoded><![CDATA[<p><a href="https://en.wikipedia.org/wiki/Database_transaction">Transactions</a> are an integral mechanism of databases, without them we could hardly ensure data consistency. Well, we could of course, but it would be a lot more work. <a href="https://en.wikipedia.org/wiki/Database_transaction">JDBC</a> has of course support for transactions, but it also supports so called "Savepoints", which we will have a look at today.</p>
<h3 style="padding-top: 10px">What are transactions?</h3>
<p>Normally, I'd assume that everyone of you knows what transactions are and what they are used for, but today I will quickly rehash it to make sure. Transactions enable us to define groups of statements to be executed on a database with all either succeeding or all failing. Imagine the following statements which might be executed on a database as one action:</p>
<div class="codesnip-container">
<pre style="line-height: 14px">
1: Insert record into A
2: Update record of B
3: Update another record of B
4: Insert record into C
</pre>
</div>
<p>This might happen in the background if you click a button or do something similar. This example is straightforward but if we start thinking about possible problems we will soon realize that there is a lot of potential for things going wrong. For example if statement #3 would fail we would miss records in the tables B and C. Overall, our data would be in an inconsistent state after that. To make sure that it does not happen, we can define these statements as a single transaction.</p>
<div class="codesnip-container">
<pre style="line-height: 14px">
Transaction
  |-Insert record into A
  |-Update record of B
  |-Update another record of B
  |-Insert record into C
  \-Commit
</pre>
</div>
<p>If one of these statements fail, all changes done by previous statements can be undone and the database will return to the state before we started manipulating it. That is great, because we can now guarantee that even though an error has happened, the data will remain in a consistent state.</p>
<p>We could even extend that with additional application logic, for example we insert three records and then we check if the values of all records add up to a certain threshold, if yes, we simply undo the changes. Or if we notice that a constraint has been violated (though, pretty much all databases support constraint definitions in one way or the other). Additionally, transactions are completely isolated from all other connected clients. That means that if we start a transaction and insert a record into table A, all other clients will not see this record until we commit our changes. So the data is never in an inconsistent state, not even temporarily or transiently.</p>
<h3 style="padding-top: 10px">What are Savepoints?</h3>
<p><a href="https://en.wikipedia.org/wiki/Savepoint">Savepoints</a> are sub-transactions within another transaction. It allows to undo parts of an ongoing transaction. </p>
<p>Another example:</p>
<div class="codesnip-container">
<pre style="line-height: 14px">
Transaction
  |-Insert record into A
  |-Insert child record into B
  |-Insert child record into B
  |-Insert another record into A
  |-Insert child record into B
  |-Insert child record into B
  |-Insert another record into A
  |-Insert child record into B
  |-Insert child record into B
  \-Commit
</pre>
</div>
<p>This is a little bit more fabricated and complicated, assume we want to insert three master records with two detail records each. The following conditions apply:</p>
<ul>
<li>If a master record fails to insert, nothing should be inserted.</li>
<li>If a detail record fails to insert, the corresponding master record should also not be inserted.</li>
</ul>
<p>This is hard to do with a simple transaction, but is quite easy when it comes to using savepoints:</p>
<div class="codesnip-container">
<pre style="line-height: 14px">
Transaction
  |-Savepoint 1
  |   |-Insert record into A
  |   |-Insert child record into B
  |   \-Insert child record into B
  |-Savepoint 2
  |   |-Insert another record into A
  |   |-Insert child record into B
  |   \-Insert child record into B
  |-Savepoint 3
  |   |-Insert another record into A
  |   |-Insert child record into B
  |   \-Insert child record into B
  \-Commit
</pre>
</div>
<p>We create a savepoint before the insert of the master record, if the insert of the master record fails we rollback the transaction, if the insert of a detail record fails we rollback to the savepoint we created earlier. This allows quite complicated and nested transactions, especially because there is no defined limit to how deep savepoints can be nested.</p>
<h3 style="padding-top: 10px">Error behavior</h3>
<p>Of course it can always happen that a statement fails for one reason or another, so it is important to know how the database behaves once an error occurred. We built ourselves another simple example:</p>
<div class="codesnip-container">
<pre style="line-height: 14px">
Transaction
  |-Insert record into A
  |-Insert record into B (this fails)
  |-Insert record into C
  \-Commit
</pre>
</div>
<p>We insert three records, and the second one fails to insert. How should the database behave in such a situation? Turns out that this differs between different database systems.</p>
<h4 style="padding-top: 10px">Silent/Automatic restore to a previous state</h4>
<p>Many databases perform a simple "silent/automatic restore to a previous state", all changes done (if any) of the current statement are undone and the transaction can be treated like the failing statement never happened. With the example above, and assuming that we do not cancel the transaction on an error, the records would be inserted into A and C.</p>
<p>In our tests <a href="http://www.oracle.com/technetwork/database/enterprise-edition/overview/index.html">Oracle</a>, <a href="https://www.mysql.com/">MySQL</a>/<a href="https://mariadb.org/">MariaDB</a>, <a href="http://www.h2database.com/html/main.html">H2</a> and <a href="https://www.sqlite.org/">SQLite</a> were all behaving this way.</p>
<h4 style="padding-top: 10px">Requiring manual recovery</h4>
<p><a href="https://www.postgresql.org/">PostgresSQL</a> requires to perform a "manual recovery" from a failed statement. So that once an error occurred during a transaction, the user has to revert to a (manually) set savepoint or rollback the complete transaction. We will go into details on that later.</p>
<h4 style="padding-top: 10px">Reverting everything and happily continuing</h4>
<p><a href="https://www.microsoft.com/en-us/sql-server/sql-server-2016">MS SQL</a> on the other hand has a quite different approach. When an error occurs during a transaction, all changes are (automatically) rolled back but the transaction can still be used. So in our example, only the record in C would be inserted.</p>
<h3 style="padding-top: 10px">PostgreSQL JDBC and Savepoints</h3>
<p>Back to <a href="https://www.postgresql.org/">PostgresSQL</a> and how it requires manual recovery. When a statement fails within a transaction in PostgreSQL, the transaction enters the aborted state and one can then see an error like the one below if further statements are issued:</p>
<blockquote><p>
Current transaction is aborted, commands ignored until end of transaction block.
</p></blockquote>
<p>What that means is simple that the connection/server is still waiting on input on what to do with the transaction. There are three possible ways to recover from there:</p>
<ol>
<li><a href="https://www.postgresql.org/docs/9.6/static/sql-rollback.html">Rollback</a> the complete transaction</li>
<li><a href="https://www.postgresql.org/docs/9.6/static/sql-commit.html">Commit</a>, which will be transformed into a rollback at this point</li>
<li><a href="https://www.postgresql.org/docs/9.6/static/sql-rollback-to.html">Rollback to a savepoint</a></li>
</ol>
<p>But these actions must be initiated by the user before the transaction can be further used (or not, if it is being rolled back completely). If one wants to emulate the behavior of other databases in PostgreSQL, every statement that is executed within a transaction has to be "wrapped" with a savepoint, in pseudo-code:</p>
<div class="codesnip-container" >
<div class="java codesnip" style="font-family:monospace;">begin transaction<br />
&nbsp; &nbsp; savepoint<br />
&nbsp; &nbsp; <span class="kw1">try</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; execute statement<br />
&nbsp; &nbsp; &nbsp; &nbsp; release savepoint<br />
&nbsp; &nbsp; <span class="kw1">catch</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; rollback to savepoint<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; ...<br />
<span class="me1">commit</span></div>
</div>
<p>Even though that seems tedious, that is not the case. If you have such a requirement you already have central point through which all statements pass before being executed, so this can be implemented easily.</p>
<h3 style="padding-top: 10px">JVx and Savepoints</h3>
<p>In our case it is DBAccess, our main datasource. Because every database interaction has to pass through DBAccess (in one way or the other), we could <a href="https://oss.sibvisions.com/index.php?do=details&amp;task_id=1870&amp;project=2">easily implement such emulation at a low-level</a> and it is automatically available to all users. To be exact, DBAccess has received internal support to wrap all statements in savepoints when configured to do so. This configuration possibility is protected and is currently only used by the PostgresSQL DBAccess extension. It does exactly what it says on the tin and is only active when enabled and automatic commits have been turned off. So this change does have no effect on any other database but PostgreSQL.</p>
<p>We already <a href="https://oss.sibvisions.com/index.php?do=details&amp;task_id=1881&amp;project=2">have plans to extend this basic savepoint support</a> with a public API which allows users of JVx to utilize this new functionality. One of the ideas that we are currently discussing is to provide the ability to create named savepoints. A simple mockup of that idea:</p>
<div class="codesnip-container" >
<div class="java codesnip" style="font-family:monospace;">
<ol>
<li class="li2">
<div class="de2"><span class="co1">// Switch off auto commit to use transactions.</span></div>
</li>
<li class="li2">
<div class="de2">dbAccess.<span class="me1">setAutoCommit</span><span class="br0">&#40;</span><span class="kw2">false</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp;</div>
</li>
<li class="li2">
<div class="de2"><span class="co1">// Insert some data.</span></div>
</li>
<li class="li2">
<div class="de2">dbStorage.<span class="me1">insert</span><span class="br0">&#40;</span>aRecord<span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li2">
<div class="de2">dbStorage.<span class="me1">insert</span><span class="br0">&#40;</span>anotherRecord<span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp;</div>
</li>
<li class="li2">
<div class="de2"><span class="co1">// This part is optional.</span></div>
</li>
<li class="li2">
<div class="de2"><span class="kw1">try</span></div>
</li>
<li class="li2">
<div class="de2"><span class="br0">&#123;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; dbAccess.<span class="me1">setSavepoint</span><span class="br0">&#40;</span><span class="st0">&quot;NAME&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; </div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; dbStorage.<span class="me1">insert</span><span class="br0">&#40;</span>yetAnotherRecord<span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; dbStorage.<span class="me1">update</span><span class="br0">&#40;</span>someOtherRecord<span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li2">
<div class="de2"><span class="br0">&#125;</span></div>
</li>
<li class="li2">
<div class="de2"><span class="kw1">catch</span> <span class="br0">&#40;</span>DataSourceException dse<span class="br0">&#41;</span></div>
</li>
<li class="li2">
<div class="de2"><span class="br0">&#123;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; log.<span class="me1">error</span><span class="br0">&#40;</span>dse<span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; dbAccess.<span class="me1">rollbackTo</span><span class="br0">&#40;</span><span class="st0">&quot;NAME&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li2">
<div class="de2"><span class="br0">&#125;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp;</div>
</li>
<li class="li2">
<div class="de2">dbAccess.<span class="me1">commit</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
</ol>
</div>
</div>
<p>As said, we are currently in the process of discussing such possibilities but definitely want to provide such an API at one point.</p>
<h3 style="padding-top: 10px">Conclusion</h3>
<p>As it turns out, the "special" behavior of PostgreSQL isn't as special as it seems to be. It is a design decision that was taken and that is understandable. Changing this behavior now, 20+ years in, is out of the question as it would require a substantial effort to make sure that this behavior is backwards compatible. The gains from such a change on the other hand would be very little, as it is a quite specialized case in which this behavior matters and  the "fix" is rather easy.</p>
]]></content:encoded>
			<wfw:commentRss>https://blog.sibvisions.com/2018/02/12/jvx-postgresql-savepoints/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
