Hibernation generating duplicate UUIDs

We have 6 node Red Hat 4.4.7 / Linux 2.6.32, each node runs a Java application that creates records in the central Oracle database using Hibernate 3.3.2.GA.

We ran into an issue where Hibernate generates duplicate UUIDs.

The Java class in question is defined as follows:

@Entity
@Table(name = "X_Y")
@GenericGenerator(name = "x-y-uuid", strategy = "uuid")
public class XY implements ... {
    @Id
    @Column(name = "X_Y_ID")
    @GeneratedValue(generator = "x-y-uuid")
    private String id;
    ...
}

      

Using this definition, which we have used successfully for a while, we ran into duplicate X_Y_ID keys. We disabled the unique limit on X_Y_ID and restarted the process. In the meantime, we started digging into possible errors in our code, as well as in Hibernate code. Reading Hibernate UUIDHexGenerator

it would appear that the first 8 characters of the UUID are based on the IP address of the machine, while the second 8 characters are the JVM start time.

After completing the process with the unique restriction on X_Y_ID disabled, we performed some analysis of the received UUIDs. We found that there were actually 59 identical X_Y_ID values. To our surprise, the request:

select SUBSTR(X_Y_ID,1,8), COUNT(*)
from X_Y
group by SUBSTR(X_Y_ID,1,8)

      

it is indicated that all 6 cars have the same first 8 characters. Request:

select SUBSTR(X_Y_ID,9,8), COUNT(*)
from X_Y
group by SUBSTR(X_Y_ID,9,8)

      

gave

"49d99de6"  2148309
"49d99e3c"  2044966
"49d99def"  2228095
"49d99df2"  2091068
"49d99dee"  4110661

      

As you can see, there are 5 lines with the last one, which is about twice the number of lines. This in itself is not surprising. (All this means that the JVM on two different machines starts up within 256ms of each other).

Further investigation revealed that the value generated for the first eight characters ff808081

corresponds to IP address 127.0.0.1, localhost.

Running ifconfig

on one of these machines gives (as an example):

eth0      Link encap:Ethernet  HWaddr 00:50:56:81:2C:20  
          inet addr:10.191.8.50  Bcast:10.191.63.255  Mask:255.255.192.0
          inet6 addr: fe80::250:56ff:fe81:2c20/64 Scope:Link
          ...

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          ...

      

My questions:

  • How is it possible that the IP address seen by Hibernate is 127.0.0.1 and not 10.191.8.50?
  • What can we do to prevent this on a deployed system?
+3


source to share


1 answer


As noted in the comments @thatotherguy, Hibernate implementation AbstractUUIDGenerator

and UUIDHexGenerator

quite far from RFC-4122 compliance. I never really realized how bad the implementation was until I looked more closely.

As an aside, taking its implementation for what it is, the root cause of your problem here comes down to UUIDHexGenerator

s
use InetAddress.getLocalHost()

(via AbstractUUIDGenerator

) to get a "unique" value. If a lookup for your hostname name results in 127.0.0.1 (for example its in your file /etc/hosts

), or if the hostname is "local", that's what it will use.

You have several options:



Option 1 is the simplest quick fix if it works for you but may have maintenance / deployment issues and, again, doesn't actually generate well-formed UUIDs. Ultimately, option 2 using UUID

(or option 4 with an appropriate strategy) is probably the most correct.

There is an article describing various strategies for assigning UUIDs for Hibernate , which may contain more useful information and examples.

+2


source







All Articles