|
本帖最后由 Yong Huang 于 2015-2-23 13:51 编辑
Thank you. Now I realize this is something I've read before. See the first "and we said" by Tom Kyte
https://asktom.oracle.com/pls/ap ... 6077843300346542181
He suggested using
"mod(session/process_id,some_small_number) so you get things like 23, 56, 89 and so on - just 1 or 2 or three digits"
as the middle part instead of simply using userenv('sessionid'), in the 3-part primary key (instance number || middle part || sequence value). That's a very crucial modification, and needs one caveat I'll explain below.
No doubt there will never be collision (in the sense of unique key violation) between RAC instances. But what about on the same instance? That's the scenario I described in msg #14. Let's say your sequence has cache 1000 as you said. Suppose the first session on instance 1 has SID 7100 and is the first session to use the sequence i.e. nextval is 1. So the session constructs the PK as 171001. Now suppose the second session happens to be on instance 1 too and its SID is 7 and uses sequence value 1001 (remember the cache is 1000). So its constructed PK is 171001. That's a collision!
Tom's suggestion is to use a mod() function to generate a "random" number instead of SID. One important rule not to be violated is that these numbers must be of the same number of digits. The result of this mod() cannot be e.g. 7100 and then 7. If the mod() is supposed to generate 4-digit numbers (i.e. at most 9999) and the result is 7, it should be padded to 0007; alternatively, limit the range to between 1000 and 9999.
Actually, I'm not sure if the rule that the middle part of the PK has a known number of digits is a guarantee that the resultant PK is collision-free. Here's a hypothesis I propose to be proved or disproved by people good at math:
1. M and N are two strings composed of digits only (0 through 9), and N does not begin with 0.
2. The number of digits (or characters) in M is always the same.
3. All instances of N are unique, i.e. no two instance of N are the same (Ni != Nj, where i != j for any i and j).
4. A string S is the concatenation of M and N in that order (S = M || N).
5. Hypothesis: There do not exist two instances of S, S1=M1||N1 and S2=M2||N2, such that S1 = S2.
For now, the hypothesis does not take into account of the initial difference between N1 and N2 (i.e. cache value of the Oracle sequence). |
|