[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

Björn Hamrin (JIRA) noreply at atlassian.com
Wed May 5 07:52:08 EDT 2010


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

Björn Hamrin commented on HHH-3608:
-----------------------------------

I've had similar problems with duplicate primary keys from an Oracle sequence. I agree that the problem is the two consecutive calls to callback.getNextValue() and the assumption that no other thread or VM manages to call callback.getNextValue() in between. The other odd thing about the two calls to callback.getNextValue() in the generate() function in PooledOptimizer is that always leaves an extra large gap in the sequence when a server starts up, as noted by errorken (part 3). The solution proposed by Adrian Shum is to use callback.getNextValue() as the bottom value instead of the top value. That should certainly work but changes the behavior. I would simply propose that one always set the value to hiValue - incrementSize, when callback.getNextValue() has been called. The only time callback.getNextValue() needs to be called twice is when a sequence is completely new, since it is likely to return 1 the very first time. I would would propose a change of the generate() to the following:

public Serializable generate(AccessCallback callback) {
  if ( hiValue < 0 ) {
    hiValue = callback.getNextValue();
    if ( hiValue <= incrementSize )
      hiValue = callback.getNextValue();
    value = hiValue - incrementSize;
  }
  else if ( value >= hiValue ) {
    hiValue = callback.getNextValue();
    value = hiValue - incrementSize;
  }
  return make( value++ );
}

I have tested this by plugging in a custom optimizer and running some tests. It appears to work. If anyone can see problem with this solution I would appreciate feedback.


> 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: 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