Thread: BUG #10847: Connection.setSavepoint()/releaseSavepoint() is not thread-safe
BUG #10847: Connection.setSavepoint()/releaseSavepoint() is not thread-safe
From
christian@schlichtherle.de
Date:
The following bug has been logged on the website: Bug reference: 10847 Logged by: Christian Schlichtherle Email address: christian@schlichtherle.de PostgreSQL version: 9.3.4 Operating system: OS X 10.9.3 Description: I am not sure if this is a bug or a feature. One might argue that you shouldn't share a connection between threads. Anyway, following is a standalone test to reproduce the issue in PostgreSQL 9.3.4 using the JDBC driver version 9.3-1101-jdbc41: <pre><code> package cpssd.db; import org.junit.Test; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Savepoint; import java.util.concurrent.CountDownLatch; /** @author Christian Schlichtherle */ public class Ticket251IT { private static final String CONNECTION_STRING = "jdbc:postgresql:postgres"; private static final int NUM_THREADS = 2; @Test public void foo() throws SQLException, InterruptedException { try (Connection c = DriverManager.getConnection(CONNECTION_STRING)) { c.setAutoCommit(false); final Runnable task = new Runnable() { final CountDownLatch startSignal = new CountDownLatch(NUM_THREADS); @Override public void run() { try { startSignal.countDown(); startSignal.await(); // FIXME: This idiom doesn't work on a shared connection! Savepoint sp = c.setSavepoint(); try { // Insert transaction script here... } finally { c.releaseSavepoint(sp); } } catch (SQLException | InterruptedException e) { e.printStackTrace(); } } }; final Thread[] threads = new Thread[NUM_THREADS]; for (int i = 0; i < threads.length; i++) (threads[i] = new Thread(task)).start(); for (Thread thread : threads) thread.join(); }, } } </code></pre> When run, this code frequently outputs the following stack trace: <pre><code> org.postgresql.util.PSQLException: ERROR: no such savepoint at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2161) at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1890) at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:255) at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:559) at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:403) at org.postgresql.jdbc2.AbstractJdbc2Connection.execSQLUpdate(AbstractJdbc2Connection.java:376) at org.postgresql.jdbc3.AbstractJdbc3Connection.releaseSavepoint(AbstractJdbc3Connection.java:192) at cpssd.db.Ticket251IT$1.run(Ticket251IT.java:32) at java.lang.Thread.run(Thread.java:745) </code></pre>
Re: BUG #10847: Connection.setSavepoint()/releaseSavepoint() is not thread-safe
From
Greg Stark
Date:
I think you need to report this to the JDBC mailing list at pgsql-jdbc@postgresql.org http://www.postgresql.org/list/pgsql-jdbc/ The Postgres libpq interface is most definitely not threadsafe but I don't see any indication in that stack trace that it's using libpq. It seems to be pure Java there.
Re: BUG #10847: Connection.setSavepoint()/releaseSavepoint() is not thread-safe
From
John R Pierce
Date:
On 7/3/2014 11:54 AM, Greg Stark wrote: > I think you need to report this to the JDBC mailing list at > pgsql-jdbc@postgresql.org > > http://www.postgresql.org/list/pgsql-jdbc/ > > The Postgres libpq interface is most definitely not threadsafe but I > don't see any indication in that stack trace that it's using libpq. It > seems to be pure Java there. yes, the jdbc driver is pure java. you still should avoid using a jdbc sql connection from more than one thread on the same transaction. its fine to reuse a connection between transactions as long as only one thread is using it at a time. -- john r pierce 37N 122W somewhere on the middle of the left coast