Improve generation algorithm for database system identifier.
authorTom Lane <tgl@sss.pgh.pa.us>
Sat, 26 Apr 2014 19:11:10 +0000 (15:11 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Sat, 26 Apr 2014 19:11:10 +0000 (15:11 -0400)
As noted some time ago, the original coding had a typo ("|" for "^")
that made the result less unique than intended.  Even the intended
behavior is obsolete since it was based on wanting to produce a
usable value even if we didn't have int64 arithmetic --- a limitation
we stopped supporting years ago.  Instead, let's redefine the system
identifier as tv_sec in the upper 32 bits (same as before), tv_usec
in the next 20 bits, and the low 12 bits of getpid() in the remaining
bits.  This is still hardly guaranteed-universally-unique, but it's
noticeably better than before.  Per my proposal at
<29019.1374535940@sss.pgh.pa.us>

src/backend/access/transam/xlog.c

index 88ad51f9e7d9252e78a8a73fd1cb2abf93a946da..a636bb6d2b03232c10f051661a310d8189c054b2 100644 (file)
@@ -4889,15 +4889,16 @@ BootStrapXLOG(void)
         * field, as being about as unique as we can easily get.  (Think not to
         * use random(), since it hasn't been seeded and there's no portable way
         * to seed it other than the system clock value...)  The upper half of the
-        * uint64 value is just the tv_sec part, while the lower half is the XOR
-        * of tv_sec and tv_usec.  This is to ensure that we don't lose uniqueness
-        * unnecessarily if "uint64" is really only 32 bits wide.  A person
-        * knowing this encoding can determine the initialization time of the
-        * installation, which could perhaps be useful sometimes.
+        * uint64 value is just the tv_sec part, while the lower half contains the
+        * tv_usec part (which must fit in 20 bits), plus 12 bits from our current
+        * PID for a little extra uniqueness.  A person knowing this encoding can
+        * determine the initialization time of the installation, which could
+        * perhaps be useful sometimes.
         */
        gettimeofday(&tv, NULL);
        sysidentifier = ((uint64) tv.tv_sec) << 32;
-       sysidentifier |= (uint32) (tv.tv_sec | tv.tv_usec);
+       sysidentifier |= ((uint64) tv.tv_usec) << 12;
+       sysidentifier |= getpid() & 0xFFF;
 
        /* First timeline ID is always 1 */
        ThisTimeLineID = 1;