[hibernate-issues] [Hibernate-JIRA] Commented: (HHH-3608) DB sequence numbers are not unique when using the pooled SequenceStyleGenerator in multiple JVMs with the same DB

Bryan Loofbourrow (JIRA) noreply at atlassian.com
Tue May 11 16:55:24 EDT 2010


    [ http://opensource.atlassian.com/projects/hibernate/browse/HHH-3608?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=37056#action_37056 ] 

Bryan Loofbourrow commented on HHH-3608:
----------------------------------------

Steve, if the two calls must stay in place, then what about this?

- If there are two calls, something might act in between them, causing the possibility of more than one process thinking it owns an ID
- If something does that, then that will affect the value returned by the second call

So what if the code checked to see whether secondResult - firstResult == increment. If it did not, it would then assume concurrency issues had occurred, use secondResult for the new "low" value, and loop back to repeat the "high" value request process. If that approach is workable, I'd think that it would not affect existing applications in any adverse way, so could be applied to the existing optimizer. I am not thoroughly familiar with the issues here, so I may be missing some essential point.

With this approach, there may be an edge case in which multiple processes interleave perfectly to produce a form of infinite-looping deadlock. So it may be better to fall back on simply using the new "low" value as a single value, and skipping reserving the whole increment window for that go around.That way, the worse-case interleave would simply skip sequence-caching and make some IDs go unused, which seem like tolerable side-effects for a rare case.

BTW if you have time, I'd find it very useful to hear an explanation of why you regard the existing code as "safer" despite the flaw demonstrated by the reporter's test case, and despite the evidence that a single-request case has apparently been surviving well in both the test case failed by the existing code, and in a production environment.

> DB sequence numbers are not unique when using the pooled SequenceStyleGenerator in multiple JVMs with the same DB
> -----------------------------------------------------------------------------------------------------------------
>
>                 Key: HHH-3608
>                 URL: http://opensource.atlassian.com/projects/hibernate/browse/HHH-3608
>             Project: Hibernate Core
>          Issue Type: Bug
>          Components: core
>    Affects Versions: 3.2.6, 3.3.0.GA, 3.3.0.SP1, 3.3.1
>         Environment: Hibernate 3.2.6, Oracle (any version)
>            Reporter: Matthias Gommeringer
>            Priority: Blocker
>         Attachments: CustomPooledOptimizer.java, PooledOptimizerTest.java
>
>
> We have several Application Servers (=JVMs) running each of them using Hibernate-Objects with the SequenceStyleGenerator+pooled configured. In unpredictable time intervals it happens that hibernate assigns the same ID to two completely different objects which results in a UniqueConstraintViolation exception from the database. Here an example with a description where hibernate fails:
> DB-Sequence setup:
> start=0
> increment=2
> PooledOptimizer.generate() with 2 threads (first assignment of hiValue/value):
> JVM-1                                                 JVM-2
> value=0=callback.nextval
>                                                             value=2=callback.nextval
> hiValue=4=callback.nextval
>                                                             hiValue=6=callback.nextval
> The problem's cause is in the PooledOptimizer.generate: when it initializes
> the value+hiValue for the first time it invokes callback.nextValue() twice which 
> may provide values that do not belong to each other. The reason is that 
> between the assignment of "value" and "hiValue" another JVM can retrieve a
> DB sequence value from the callback which leads to an inconsistent "value" and "hiValue"
> relation (see example above).
> A fix that works for multiple JVMs would be to invoke the "callback.getNextValue()" maximum once
> per "optimizer.generate()" call:
>     public synchronized Serializable generate(AccessCallback callback) {
>         if ( hiValue < 0 ) {
>             value = callback.getNextValue();
>             hiValue = value + incrementSize;
>         }
>         else if ( value >= hiValue ) {
>             value = callback.getNextValue();
>             hiValue = value + incrementSize;
>         }
>         return make(value++);
>     }
> I attached a testcase that prooves the described problem (you can see that the IDs "2" and "3" are assigned two times).
> I would be very thankful if this problem could be fixed very soon since it is a showstopper which
> occurs very unpredictably.

-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://opensource.atlassian.com/projects/hibernate/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira

        


More information about the hibernate-issues mailing list