Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Couple of preparedstatement bug suspects

1 view
Skip to first unread message

Roy Smith

unread,
May 8, 2008, 11:54:54 PM5/8/08
to
Hi All

I have an app which inserts rows to a table called messages. During load testing, I'm looping to insert 10,000 rows.
Intermittentently (around 5% and only after the first 6,000 or so) I'm getting the following Exception...

org.postgresql.util.PSQLException: This statement has been closed.
    at org.postgresql.jdbc2.AbstractJdbc2Statement.checkClosed(AbstractJdbc2Statement.java:2442)
    at org.postgresql.jdbc2.AbstractJdbc2Statement.getUpdateCount(AbstractJdbc2Statement.java:495)
    at org.postgresql.jdbc2.AbstractJdbc2Statement.executeUpdate(AbstractJdbc2Statement.java:309)
    at com.primetext.tl2000.dataobjects.Messages.insert(Messages.java:566)


This smells like a bug. There are other updates within my loop, and I can't promise that I'm closing all statements. Therefore if this bug is being triggered by me abusing the driver, please confirm and I'll go through all of my code ensuring that all preparedstatements are being closed.

However, there is a another aspect of this which smells like an even bigger bug...
Even though the PreparedStatement.executeUpdate is throwing an exception, the row *is* being written to the database!!
This can't possibly be valid.

best regards
Roy

Kris Jurka

unread,
May 9, 2008, 12:14:22 AM5/9/08
to

On Fri, 9 May 2008, Roy Smith wrote:

> I have an app which inserts rows to a table called messages. During load
> testing, I'm looping to insert 10,000 rows. Intermittentently (around 5%
> and only after the first 6,000 or so) I'm getting the following
> Exception...
>
> org.postgresql.util.PSQLException: This statement has been closed.
> at
> org.postgresql.jdbc2.AbstractJdbc2Statement.checkClosed(AbstractJdbc2Statement.java:2442)
> at
> org.postgresql.jdbc2.AbstractJdbc2Statement.getUpdateCount(AbstractJdbc2Statement.java:495)
> at
> org.postgresql.jdbc2.AbstractJdbc2Statement.executeUpdate(AbstractJdbc2Statement.java:309)
> at com.primetext.tl2000.dataobjects.Messages.insert(Messages.java:566)
>
> This smells like a bug. There are other updates within my loop, and I
> can't promise that I'm closing all statements. Therefore if this bug is
> being triggered by me abusing the driver, please confirm and I'll go
> through all of my code ensuring that all preparedstatements are being
> closed.
>

Is your app multi-threaded? The only way I see for this to happen is that
one thread is executing the statement and another is closing it.

> However, there is a another aspect of this which smells like an even
> bigger bug... Even though the PreparedStatement.executeUpdate is
> throwing an exception, the row *is* being written to the database!! This
> can't possibly be valid.
>

The exception is from the driver, not the server and it happens after the
query has been executed by the server. Once the server has committed the
data, there's not much the driver can do about that.

Kris Jurka

--
Sent via pgsql-jdbc mailing list (pgsql...@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-jdbc

Roy Smith

unread,
May 9, 2008, 12:41:29 AM5/9/08
to
Hi Kris

Thanks for the quick response.

No the app is not multithreaded. It's a web app and I'm the only user on my local test PC. So I start tomcat, run a single post which generates the error, stop tomcat.

I didn't understand your 2nd point. When I call PreparedStatement.executeUpdate() I have to know that the row did or did not get written. If there is a situation that an exception can be thrown after the data has been written, that exception needs to be unambiguous in telling the caller that the data is written or not.

I'm happy to provide any debug/logs which help you with this one, just let me know.

best
Roy



On Fri, May 9, 2008 at 5:14 AM, Kris Jurka <bo...@ejurka.com> wrote:


On Fri, 9 May 2008, Roy Smith wrote:

I have an app which inserts rows to a table called messages. During load testing, I'm looping to insert 10,000 rows. Intermittentently (around 5% and only after the first 6,000 or so) I'm getting the following Exception...

org.postgresql.util.PSQLException: This statement has been closed.
  at
org.postgresql.jdbc2.AbstractJdbc2Statement.checkClosed(AbstractJdbc2Statement.java:2442)
  at
org.postgresql.jdbc2.AbstractJdbc2Statement.getUpdateCount(AbstractJdbc2Statement.java:495)
  at
org.postgresql.jdbc2.AbstractJdbc2Statement.executeUpdate(AbstractJdbc2Statement.java:309)
  at com.primetext.tl2000.dataobjects.Messages.insert(Messages.java:566)

This smells like a bug. There are other updates within my loop, and I can't promise that I'm closing all statements. Therefore if this bug is being triggered by me abusing the driver, please confirm and I'll go through all of my code ensuring that all preparedstatements are being closed.


Is your app multi-threaded?  The only way I see for this to happen is that one thread is executing the statement and another is closing it.
However, there is a another aspect of this which smells like an even bigger bug... Even though the PreparedStatement.executeUpdate is throwing an exception, the row *is* being written to the database!! This can't possibly be valid.


Kris Jurka

unread,
May 9, 2008, 3:36:02 PM5/9/08
to

On Fri, 9 May 2008, Roy Smith wrote:

> No the app is not multithreaded. It's a web app and I'm the only user on my
> local test PC. So I start tomcat, run a single post which generates the
> error, stop tomcat.

Then I don't understand how it got closed mid-execution, perhaps some sort
of intermediate pooling/proxying mechanism is involved? If you can
compose a self-contained test case, I'd be happy to look at it.

> I didn't understand your 2nd point. When I call
> PreparedStatement.executeUpdate() I have to know that the row did or did
> not get written. If there is a situation that an exception can be thrown
> after the data has been written, that exception needs to be unambiguous
> in telling the caller that the data is written or not.
>

To get this control you shouldn't be using autocommit. You should turn
that off and then rollback if you get a SQLException. With autocommit,
the cats already out of the bag.

Kris Jurka

unread,
May 12, 2008, 3:02:32 AM5/12/08
to
Roy Smith wrote:
> To get this control you shouldn't be using autocommit. You should
> turn that off and then rollback if you get a SQLException. With
> autocommit, the cats already out of the bag.
>
>
> Hmmm, not sure I agree but I'm happy to be persuaded. You're saying that
> a single JDBC call is *not* atomic in and of itself? As a computer
> scientist I find that disturbing if it's true. It basically means that
> running any JDBC session in autocommit mode is bogus, since individual
> update statements become non-deterministic.

Well, in general autocommit isn't safe and neither is non-autocommit.
If you get a network disconnect at just the wrong time (during commit),
you can't tell what happened to your transaction. You'll get a
SQLException informing you your connection is gone, but did it commit or
not? You need two phase commit (XA) to be able to name and lookup in
doubt transactions at a later date in case something bad happens. In
your case something odd is going on (which we may still be able to
resolve), but is it worth moving every single application to XA to
defend against these possibilities? I don't think so.

> I do appreciate that where an executeUpdate is carrying out more than
> one database write there isn't much you can do about it.

Even in the single write case, there is some code in the JDBC driver and
it must have some failure modes right? What about an out of memory
condition when trying to retrieve the server's response? The server has
committed it and the driver can't interpret that result.

> Nested transactions would be an answer, but of course there is no
> such thing.
>

There are savepoints, but again I don't see how that's helpful in
autocommit mode.

Kris Jurka

unread,
May 19, 2008, 11:16:09 PM5/19/08
to

On Fri, 9 May 2008, Kris Jurka wrote:

> On Fri, 9 May 2008, Roy Smith wrote:
>
>> No the app is not multithreaded. It's a web app and I'm the only user on my
>> local test PC. So I start tomcat, run a single post which generates the
>> error, stop tomcat.
>
> Then I don't understand how it got closed mid-execution, perhaps some sort of
> intermediate pooling/proxying mechanism is involved? If you can compose a
> self-contained test case, I'd be happy to look at it.

Any progress on creating a test case?

0 new messages