Обсуждение: PSQLException: The column name was not found in this ResultSet.

Поиск
Список
Период
Сортировка

PSQLException: The column name was not found in this ResultSet.

От
Michael Fork
Дата:
postgresql-9.0-801.jdbc3.jar

PostgreSQL 8.3.7 on amd64-portbld-freebsd7.2, compiled by GCC cc (GCC) 4.2.1
20070719  [FreeBSD]

Caused by: org.postgresql.util.PSQLException: The column name mdn was not found
in this ResultSet.
        at
org.postgresql.jdbc2.AbstractJdbc2ResultSet.findColumn(AbstractJdbc2ResultSet.java:2562)

        at
org.postgresql.jdbc2.AbstractJdbc2ResultSet.getString(AbstractJdbc2ResultSet.java:2405)

        at
org.apache.commons.dbcp.DelegatingResultSet.getString(DelegatingResultSet.java:225)


I receive the above error message when accessing the JDBC resultset from
multiple threads.  It does not occur consistently, but roughly every 20 or 30
runs and almost immediately upon invocation.  Looking
at org/postgresql/jdbc2/AbstractJdbc2ResultSet.java it appears there is a race
condition around building columnNameIndexMap

        if (columnNameIndexMap == null)         {             columnNameIndexMap
= new HashMap(fields.length * 2);             // The JDBC spec says when you
have duplicate columns names,             // the first one should be returned.
So load the map in             // reverse order so the first ones will overwrite
later ones.             for (int i = fields.length - 1; i >= 0; i--)
{
columnNameIndexMap.put(fields[i].getColumnLabel().toLowerCase(Locale.US), new
Integer(i + 1));             }         }
I cannot confirm this, but I would guess that on thread enters, has the NULL map
and creates the new HashMap.  The second thread enters, sees the non-NULL
columnNameIndexMap, and gets to the HashMap.get call prior to the first thread
fully populating the map.  If this is the problem, would wrapping the IF block
in a synchronized(this) block fix it?
Thanks.


Michael


Re: PSQLException: The column name was not found in this ResultSet.

От
Kris Jurka
Дата:

On Mon, 8 Nov 2010, Michael Fork wrote:

> Caused by: org.postgresql.util.PSQLException: The column name mdn was not found
> in this ResultSet.
>
> I receive the above error message when accessing the JDBC resultset from
> multiple threads.  It does not occur consistently, but roughly every 20
> or 30 runs and almost immediately upon invocation.  Looking at
> org/postgresql/jdbc2/AbstractJdbc2ResultSet.java it appears there is a
> race condition around building columnNameIndexMap
>
> I cannot confirm this, but I would guess that on thread enters, has the
> NULL map and creates the new HashMap.  The second thread enters, sees
> the non-NULL columnNameIndexMap, and gets to the HashMap.get call prior
> to the first thread fully populating the map.  If this is the problem,
> would wrapping the IF block in a synchronized(this) block fix it?
>

That looks like the correct diagnosis and fix to me.

Kris Jurka


Re: PSQLException: The column name was not found in this ResultSet.

От
Samuel Gendler
Дата:
On Tue, Nov 9, 2010 at 4:10 PM, Kris Jurka <books@ejurka.com> wrote:


On Mon, 8 Nov 2010, Michael Fork wrote:

Caused by: org.postgresql.util.PSQLException: The column name mdn was not found
in this ResultSet.

I receive the above error message when accessing the JDBC resultset from multiple threads.  It does not occur consistently, but roughly every 20 or 30 runs and almost immediately upon invocation.  Looking at org/postgresql/jdbc2/AbstractJdbc2ResultSet.java it appears there is a race condition around building columnNameIndexMap

I cannot confirm this, but I would guess that on thread enters, has the NULL map and creates the new HashMap.  The second thread enters, sees the non-NULL columnNameIndexMap, and gets to the HashMap.get call prior to the first thread fully populating the map.  If this is the problem, would wrapping the IF block in a synchronized(this) block fix it?

That looks like the correct diagnosis and fix to me.


That would only be a valid fix if ResultSet is intended to be inherently threadsafe. I wouldn't think that is the case.  There is no mention of thread safety at all in the javadocs, which I would always take to imply that there is no implicit thread safety.  Code which utilizes a ResultSet should do so in a thread safe manner, rather than attempting to make the resultset implementation thread-safe - unless my assumptions about the intent of the interface designers is incorrect.

 

Re: PSQLException: The column name was not found in this ResultSet.

От
Michael Fork
Дата:
Looking into this further, I think the initial fix was insufficient.  I think
there are two ways to go.  One is to synchronize the entire findColumnIndex.
Since we are using a standard HashMap and not a synchronized one, the additional
put could cause issues when doing a get if a resize was underway.  The
alternative would be to use Collections.synchronizedMap at instantiation of the
HashMap and wrap the initial load of it in the synchronized(this) block as
proposed below.  Once loaded, the get/puts would be synchronized by the map.

Thanks.

Michael

----- Original Message ----
From: Kris Jurka <books@ejurka.com>
To: Michael Fork <mfork00@yahoo.com>
Cc: pgsql-jdbc@postgresql.org
Sent: Tue, November 9, 2010 7:10:18 PM
Subject: Re: [JDBC] PSQLException: The column name <col> was not found in this
ResultSet.



On Mon, 8 Nov 2010, Michael Fork wrote:

> Caused by: org.postgresql.util.PSQLException: The column name mdn was not
found
> in this ResultSet.
>
> I receive the above error message when accessing the JDBC resultset from
>multiple threads.  It does not occur consistently, but roughly every 20 or 30
>runs and almost immediately upon invocation.  Looking at
>org/postgresql/jdbc2/AbstractJdbc2ResultSet.java it appears there is a race
>condition around building columnNameIndexMap
>
> I cannot confirm this, but I would guess that on thread enters, has the NULL
>map and creates the new HashMap.  The second thread enters, sees the non-NULL
>columnNameIndexMap, and gets to the HashMap.get call prior to the first thread
>fully populating the map.  If this is the problem, would wrapping the IF block
>in a synchronized(this) block fix it?
>

That looks like the correct diagnosis and fix to me.

Kris Jurka


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


Re: PSQLException: The column name was not found in this ResultSet.

От
Lew
Дата:
On 11/10/2010 12:27 AM, Samuel Gendler wrote:
> On Tue, Nov 9, 2010 at 4:10 PM, Kris Jurka <books@ejurka.com
> <mailto:books@ejurka.com>> wrote:
>
>
>
>     On Mon, 8 Nov 2010, Michael Fork wrote:
>
>         Caused by: org.postgresql.util.PSQLException: The column name
>         mdn was not found
>         in this ResultSet.
>
>         I receive the above error message when accessing the JDBC
>         resultset from multiple threads.  It does not occur
>         consistently, but roughly every 20 or 30 runs and almost
>         immediately upon invocation.  Looking at
>         org/postgresql/jdbc2/AbstractJdbc2ResultSet.java it appears
>         there is a race condition around building columnNameIndexMap
>
>         I cannot confirm this, but I would guess that on thread enters,
>         has the NULL map and creates the new HashMap.  The second thread
>         enters, sees the non-NULL columnNameIndexMap, and gets to the
>         HashMap.get call prior to the first thread fully populating the
>         map.  If this is the problem, would wrapping the IF block in a
>         synchronized(this) block fix it?

IT is possible without proper synchronization for thread A to instantiate and
fully population a shared Map reference, and for thread B subsequently to see
a 'null', empty or partially populated view from that reference.

>     That looks like the correct diagnosis and fix to me.
>
>
> That would only be a valid fix if ResultSet is intended to be inherently
> threadsafe. I wouldn't think that is the case.  There is no mention of
> thread safety at all in the javadocs, which I would always take to imply
> that there is no implicit thread safety.  Code which utilizes a
> ResultSet should do so in a thread safe manner, rather than attempting
> to make the resultset implementation thread-safe - unless my assumptions
> about the intent of the interface designers is incorrect.

It is meaningless to talk about thread safety with respect to interfaces.

--
Lew

Re: PSQLException: The column name was not found in this ResultSet.

От
Maciek Sakrejda
Дата:
>> Code which utilizes a
>> ResultSet should do so in a thread safe manner, rather than attempting
>> to make the resultset implementation thread-safe - unless my assumptions
>> about the intent of the interface designers is incorrect.
>
> It is meaningless to talk about thread safety with respect to interfaces.

I think Samuel was talking about the thread-safety guarantees of the
interface contract. E.g., the List interface does not guarantee
thread-safety, so if you want to call add() on multiple Lists from
multiple threads, synchronization is your responsibility. If the
interface contract of ResultSet does not guarantee thread safety, I
don't see why the driver should bother to offer it there. Hashtable,
Vector, and StringBuffer took that route, and look at them now.
---
Maciek Sakrejda | System Architect | Truviso

1065 E. Hillsdale Blvd., Suite 215
Foster City, CA 94404
(650) 242-3500 Main
www.truviso.com

Re: PSQLException: The column name was not found in this ResultSet.

От
Maciek Sakrejda
Дата:
> ...you want to call add() on multiple Lists from multiple threads...

That should, of course, be "on the same List from multiple threads".
---
Maciek Sakrejda | System Architect | Truviso

1065 E. Hillsdale Blvd., Suite 215
Foster City, CA 94404
(650) 242-3500 Main
www.truviso.com

Re: PSQLException: The column name was not found in this ResultSet.

От
Lew
Дата:
Samuel Gendler wrote:
>>> Code which utilizes a
>>> ResultSet should do so in a thread safe manner, rather than attempting
>>> to make the resultset implementation thread-safe - unless my assumptions
>>> about the intent of the interface designers is incorrect.

Lew wrote:
>> It is meaningless to talk about thread safety with respect to interfaces.

Maciek Sakrejda wrote:
> I think Samuel was talking about the thread-safety guarantees of the
> interface contract. E.g., the List interface does not guarantee

It is meaningless to talk about thread safety with respect to interfaces.
Thread safety is an implementation guarantee (or lack thereof), not
discernible nor enforceable by an interface.

> thread-safety, so if you want to call add() on multiple Lists from
> multiple threads, synchronization is your responsibility. If the

If you want to call 'add()' on multiple 'List's from multiple threads, even if
you are using thread-safe implementations, if the actions among the several
list instances needs to be coordinated then synchronization is your
responsibility.

> interface contract of ResultSet does not guarantee thread safety, I

Because interfaces cannot guarantee thread safety.

> don't see why the driver should bother to offer it there. Hashtable,
> Vector, and StringBuffer took that route, and look at them now.

Those are not interfaces.

It is impossible for ResultSet to guarantee thread safety.  It is also
impossible for List to guarantee thread safety, yet
'java.util.concurrent.CopyOnWriteArrayList<E>' is a "thread-safe variant of
ArrayList".

Thread safety lives or dies only in the implementation.

--
Lew

Re: PSQLException: The column name was not found in this ResultSet.

От
Lew
Дата:
Maciek Sakrejda wrote:
>> ...you want to call add() on multiple Lists from multiple threads...
>
> That should, of course, be "on the same List from multiple threads".

To put that in context with the correction:
> if you want to call add() on the same List from
> multiple threads, synchronization is your responsibility.

Not if you use a thread-safe 'List'.  Then the implementation handles thread
safety for you.

--
Lew

Re: PSQLException: The column name was not found in this ResultSet.

От
Maciek Sakrejda
Дата:
We're getting off topic--perhaps I didn't express myself clearly.
Getting back to Samuel's original point, if the ResultSet interface
contract does not require a given implementation to provide thread
safety for these operations--and it appears that it does not--then
maybe pgjdbc should not try to provide it. If a user needs to use a
ResultSet from multiple threads, it can be synchronized externally.
---
Maciek Sakrejda | System Architect | Truviso

1065 E. Hillsdale Blvd., Suite 215
Foster City, CA 94404
(650) 242-3500 Main
www.truviso.com

Re: PSQLException: The column name was not found in this ResultSet.

От
Till Toenges
Дата:
On 2010-11-12 07:18, Maciek Sakrejda wrote:
> We're getting off topic--perhaps I didn't express myself clearly.
> Getting back to Samuel's original point, if the ResultSet interface
> contract does not require a given implementation to provide thread
> safety for these operations--and it appears that it does not--then
> maybe pgjdbc should not try to provide it. If a user needs to use a
> ResultSet from multiple threads, it can be synchronized externally.

The pgjdbc driver is supposed to be thread safe:

http://jdbc.postgresql.org/documentation/pgjdbc.html#Using+the+Driver+in+a+Multithreaded+or+a+Servlet+Environment

Whether this is good or bad doesn't matter. Has been this way forever,
can't change that now.


Till

--
Kyon, Till Toenges, tt@kyon.de, http://kyon.de
Blumenstr. 39, 47798 Krefeld, +49-2151-3292595

Re: PSQLException: The column name was not found in this ResultSet.

От
Lew
Дата:
Maciek Sakrejda wrote:
> We're getting off topic--perhaps I didn't express myself clearly.
> Getting back to Samuel's original point, if the ResultSet interface
> contract does not require a given implementation to provide thread
> safety for these operations--and it appears that it does not--then

I do not know of any interface that requires its implementations to be thread
safe, anywhere in Java.  The closest I can think of is the JPA
javax.persistence.EntityManagerFactory, all extant implementations of which
are thread-safe, but of course the interface cannot require that.

Can you think of one that does?

--
Lew

Re: PSQLException: The column name was not found in this ResultSet.

От
Florian Weimer
Дата:
* Till Toenges:

> The pgjdbc driver is supposed to be thread safe:
>
> http://jdbc.postgresql.org/documentation/pgjdbc.html#Using+the+Driver+in+a+Multithreaded+or+a+Servlet+Environment
>
> Whether this is good or bad doesn't matter. Has been this way forever,
> can't change that now.

To me, it only says that Connection objects are thread-safe.
ResultSets are a different story.  To implement them in a thread-safe
manner, you need a thread-local variables, otherwise you cannot get
wasNull() right.

--
Florian Weimer                <fweimer@bfk.de>
BFK edv-consulting GmbH       http://www.bfk.de/
Kriegsstraße 100              tel: +49-721-96201-1
D-76133 Karlsruhe             fax: +49-721-96201-99

Re: PSQLException: The column name was not found in this ResultSet.

От
Florian Weimer
Дата:
* Lew:

> I do not know of any interface that requires its implementations to be
> thread safe, anywhere in Java.  The closest I can think of is the JPA
> javax.persistence.EntityManagerFactory, all extant implementations of
> which are thread-safe, but of course the interface cannot require
> that.
>
> Can you think of one that does?

java.util.concurrent.BlockingQueue and many others from the
java.util.concurrent package.  This is not enforced by the language,
of course.

--
Florian Weimer                <fweimer@bfk.de>
BFK edv-consulting GmbH       http://www.bfk.de/
Kriegsstraße 100              tel: +49-721-96201-1
D-76133 Karlsruhe             fax: +49-721-96201-99

Re: PSQLException: The column name was not found in this ResultSet.

От
Lew
Дата:
On 11/12/2010 12:00 PM, Florian Weimer wrote:
Lew:
>> I do not know of any interface that requires its implementations to be
>> thread safe, anywhere in Java.  The closest I can think of is the JPA
>> javax.persistence.EntityManagerFactory, all extant implementations of
>> which are thread-safe, but of course the interface cannot require
>> that.
>>
>> Can you think of one that does?


> java.util.concurrent.BlockingQueue and many others from the
> java.util.concurrent package.  This is not enforced by the language,
> of course.

And therefore does not require implementations to be thread safe, as I stated.

Even the documentation for 'BlockingQueue' makes that point: "BlockingQueue
implementations are thread-safe."  Not the interface, only its implementations
are thread safe, and implicitly only the ones known at the time the Javadoc
comments were written.

--
Lew

Re: PSQLException: The column name was not found in this ResultSet.

От
Maciek Sakrejda
Дата:
> Even the documentation for 'BlockingQueue' makes that point: "BlockingQueue
> implementations are thread-safe."  Not the interface, only its
> implementations are thread safe, and implicitly only the ones known at the
> time the Javadoc comments were written.

Of course BlockingQueue does not *provide* thread safety, but it
*requires* it of its implementations. Not through any enforceable
means, but this is part of the interface contract, i.e., this is part
of what it means to be a BlockingQueue. Following the thread safety
guarantees (or lack thereof) specified in the interface contract is as
important as having put() actually put an item on the queue instead of
removing one (note that this is also not "required" by the interface).
Implementing an interface is more than just adding "implements Foo"
and writing whatever code you like in all the methods required to be
there by the compiler.

But we're getting really off-topic. Samuel suggested that the
ResultSet interface does not guarantee thread safety (i.e., it does
not promise that any implementation will be synchronized). As Till
pointed out, the PostgreSQL implementation JDBC API *does* in fact
promise thread safety (which is fine--an implementation can offer
additional guarantees here, as per Hashtable and Map). This would
suggest that we do need the fix that Michael originally suggested.

However--and I think this is the only real open issue--Florian pointed
out that the guarantees in the PostgreSQL JDBC docs could be
interpreted to mean that the PostgreSQL Connection is guaranteed to be
thread-safe while ResultSet is not (especially given the dicey
wasNull() issue).

So, any thoughts on Florian's suggestion?

---
Maciek Sakrejda | System Architect | Truviso

1065 E. Hillsdale Blvd., Suite 215
Foster City, CA 94404
(650) 242-3500 Main
www.truviso.com

Re: PSQLException: The column name was not found in this ResultSet.

От
Kris Jurka
Дата:

On Sun, 14 Nov 2010, Maciek Sakrejda wrote:

> But we're getting really off-topic. Samuel suggested that the
> ResultSet interface does not guarantee thread safety (i.e., it does
> not promise that any implementation will be synchronized). As Till
> pointed out, the PostgreSQL implementation JDBC API *does* in fact
> promise thread safety (which is fine--an implementation can offer
> additional guarantees here, as per Hashtable and Map). This would
> suggest that we do need the fix that Michael originally suggested.
>
> However--and I think this is the only real open issue--Florian pointed
> out that the guarantees in the PostgreSQL JDBC docs could be
> interpreted to mean that the PostgreSQL Connection is guaranteed to be
> thread-safe while ResultSet is not (especially given the dicey
> wasNull() issue).
>

The real question is how realistic/useful is the coding pattern in
question.  There are other known thread safety problems in the driver that
have not been dealt with.  For example two threads sharing a
PreparedStatement, one executing it while the other is simultaneously
calling setXXX on it.  The driver could synchonize this, but you'd
random behavior behavior depending on which call happened first.  So no
driver changes were made to help support this because it doesn't seem like
a reasonable coding pattern.

Perhaps Michael could provide some additional context regarding the
application and why multiple threads are processing the same ResultSet.
You can avoid wasNull problems by only using getObject, but you'd still
need to synchonize the next() calls.  And how much gain can you really get
by parallel ResultSet reading?

Kris Jurka

Re: PSQLException: The column name was not found in this ResultSet.

От
Michael Fork
Дата:
I am using the Spring Batch project
(http://static.springsource.org/spring-batch/) to complete a large, parallel job
configured to run 10 threads.
 A org.springframework.batch.item.database.JdbcCursorItemReader<T> object is
used to open the recordset using TYPE_FORWARD_ONLY and CONCUR_READ_ONLY.  I
tried following the code but was unable to figure out exactly how the recordset
object was accessed and where.

It does sound like the root of the problem lies in Spring Batch not properly
synchronizing access to a recordset object and they should address the issue
there if possible.  While I would like to see the issue in PostgreSQL JDBC
driver addressed as it was the only problem I have encountered to date, I
understand if it is not since there is no explicit thread safe guarantee around
a recordset.
 Thanks.


Michael



----- Original Message ----
From: Kris Jurka <books@ejurka.com>
To: Maciek Sakrejda <msakrejda@truviso.com>
Cc: Michael Fork <mfork00@yahoo.com>; pgsql-jdbc@postgresql.org
Sent: Sun, November 14, 2010 5:44:33 PM
Subject: Re: [JDBC] PSQLException: The column name <col> was not found in this
ResultSet.



On Sun, 14 Nov 2010, Maciek Sakrejda wrote:

> But we're getting really off-topic. Samuel suggested that the
> ResultSet interface does not guarantee thread safety (i.e., it does
> not promise that any implementation will be synchronized). As Till
> pointed out, the PostgreSQL implementation JDBC API *does* in fact
> promise thread safety (which is fine--an implementation can offer
> additional guarantees here, as per Hashtable and Map). This would
> suggest that we do need the fix that Michael originally suggested.
>
> However--and I think this is the only real open issue--Florian pointed
> out that the guarantees in the PostgreSQL JDBC docs could be
> interpreted to mean that the PostgreSQL Connection is guaranteed to be
> thread-safe while ResultSet is not (especially given the dicey
> wasNull() issue).
>

The real question is how realistic/useful is the coding pattern in question.
There are other known thread safety problems in the driver that have not been
dealt with.  For example two threads sharing a PreparedStatement, one executing
it while the other is simultaneously calling setXXX on it.  The driver could
synchonize this, but you'd random behavior behavior depending on which call
happened first.  So no driver changes were made to help support this because it
doesn't seem like a reasonable coding pattern.

Perhaps Michael could provide some additional context regarding the application
and why multiple threads are processing the same ResultSet. You can avoid
wasNull problems by only using getObject, but you'd still need to synchonize the
next() calls.  And how much gain can you really get by parallel ResultSet
reading?

Kris Jurka

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