[ 
https://issues.apache.org/jira/browse/OPENJPA-466?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Milosz Tylenda reopened OPENJPA-466:
------------------------------------


Although the patch applied (synchronization on PreparedStatement within 
NativeJDBCSeq.getSequence) does a good job on reducing the likelihood of crash, 
I am afraid we are still not free from multi-threading issue. On my one-core 
laptop I am not able to reproduce this issue (even when I remove the patch) but 
I find the problem still exists in the AbstractJDBCSeq.next method. I am able 
to reproduce the exception when I insert Thread.yield():

    public Object next(StoreContext ctx, ClassMetaData meta) {
        JDBCStore store = getStore(ctx);
        try {
            current = nextInternal(store, (ClassMapping) meta);
            Thread.yield();
            return current;
        } catch (OpenJPAException ke) {
            throw ke;
        } catch (SQLException se) {
            throw SQLExceptions.getStore(se, store.getDBDictionary());
        } catch (Exception e) {
            throw new StoreException(e);
        }
    }

This yield() simulates context switching in an real application. The context 
switch will actually seldom occur here but is possible to my knowledge. Also, I 
am able to reproduce the exception by adding some Thread.sleep calls instead of 
yield() but this is harder to reproduce.

My suggestion is to remove the synchronization from NativeJDBCSeq.getSequence 
and modify AbstractJDBCSeq.next to something like the following:

    public Object next(StoreContext ctx, ClassMetaData meta) {
        JDBCStore store = getStore(ctx);
        try {
                Object currentLocal = nextInternal(store, (ClassMapping) meta);
                current = currentLocal;
                return currentLocal;
        } catch (OpenJPAException ke) {
            throw ke;
        } catch (SQLException se) {
            throw SQLExceptions.getStore(se, store.getDBDictionary());
        } catch (Exception e) {
            throw new StoreException(e);
        }
    }


> Primary key constraint violated using (Oracle) sequence to generate ID in 
> multithreaded app
> -------------------------------------------------------------------------------------------
>
>                 Key: OPENJPA-466
>                 URL: https://issues.apache.org/jira/browse/OPENJPA-466
>             Project: OpenJPA
>          Issue Type: Bug
>    Affects Versions: 1.0.0, 1.0.1, 1.1.0, 1.2.0
>         Environment: OpenJPA 1.0.0 (also tried 1.0.1 and 1.1.0-SNAPSHOT)
> Oracle XE 10g (JDBC driver 10.2.0.3.0)
> Windows XP Pro
>            Reporter: Frank Le
>            Assignee: Tim McConnell
>            Priority: Blocker
>             Fix For: 2.0.0
>
>         Attachments: OPENJPA-466.patch
>
>
> Here's how I annotate the ID:
>     @Id
>     @SequenceGenerator(name = "FooSeq", sequenceName = "seq_foo", 
> allocationSize = 20)
>     @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "FooSeq")
>     private Long id;
> Here's how I create the (Oracle) sequence:
> CREATE SEQUENCE seq_foo START WITH 1 INCREMENT BY 1;
> I get a primary key unique constraint violated in a multithreaded app i.e. it 
> doesn't happen in single-threaded!
> You can simply reproduce this error by either create blocking queue or 
> blocking thread pool say size 5 to insert 10000+ object.

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.

Reply via email to