http://dinglin.iteye.com/blog/1487537
http://www.cnblogs.com/jdonson/archive/2009/07/22/1528466.html
http://blog.chinaunix.net/uid-26495963-id-3150576.html
http://www.ietf.org/rfc/rfc4122.txt
http://blog.csdn.net/sasoritattoo/article/details/10365847
mysql5.7
uuid 源代码:
String *Item_func_uuid::val_str(String *str) { DBUG_ASSERT(fixed == 1); char *s; THD *thd= current_thd; mysql_mutex_lock(&LOCK_uuid_generator); if (! uuid_time) /* first UUID() call. initializing data */ { ulong tmp=sql_rnd_with_mutex(); uchar mac[6]; int i; if (my_gethwaddr(mac)) { /* purecov: begin inspected */ /* generating random "hardware addr" and because specs explicitly specify that it should NOT correlate with a clock_seq value (initialized random below), we use a separate randominit() here */ randominit(&uuid_rand, tmp + (ulong) thd, tmp + (ulong)global_query_id); for (i=0; i < (int)sizeof(mac); i++) mac[i]=(uchar)(my_rnd(&uuid_rand)*255); /* purecov: end */ } s=clock_seq_and_node_str+sizeof(clock_seq_and_node_str)-1; for (i=sizeof(mac)-1 ; i>=0 ; i--) { *--s=_dig_vec_lower[mac[i] & 15]; *--s=_dig_vec_lower[mac[i] >> 4]; } randominit(&uuid_rand, tmp + (ulong) server_start_time, tmp + (ulong) thd->status_var.bytes_sent); set_clock_seq_str(); } ulonglong tv= my_getsystime() + UUID_TIME_OFFSET + nanoseq; if (likely(tv > uuid_time)) { /* Current time is ahead of last timestamp, as it should be. If we "borrowed time", give it back, just as long as we stay ahead of the previous timestamp. */ if (nanoseq) { DBUG_ASSERT((tv > uuid_time) && (nanoseq > 0)); /* -1 so we won't make tv= uuid_time for nanoseq >= (tv - uuid_time) */ ulong delta= min<ulong>(nanoseq, (ulong) (tv - uuid_time -1)); tv-= delta; nanoseq-= delta; } } else { if (unlikely(tv == uuid_time)) { /* For low-res system clocks. If several requests for UUIDs end up on the same tick, we add a nano-second to make them different. ( current_timestamp + nanoseq * calls_in_this_period ) may end up > next_timestamp; this is OK. Nonetheless, we'll try to unwind nanoseq when we get a chance to. If nanoseq overflows, we'll start over with a new numberspace (so the if() below is needed so we can avoid the ++tv and thus match the follow-up if() if nanoseq overflows!). */ if (likely(++nanoseq)) ++tv; } if (unlikely(tv <= uuid_time)) { /* If the admin changes the system clock (or due to Daylight Saving Time), the system clock may be turned *back* so we go through a period once more for which we already gave out UUIDs. To avoid duplicate UUIDs despite potentially identical times, we make a new random component. We also come here if the nanoseq "borrowing" overflows. In either case, we throw away any nanoseq borrowing since it's irrelevant in the new numberspace. */ set_clock_seq_str(); tv= my_getsystime() + UUID_TIME_OFFSET; nanoseq= 0; DBUG_PRINT("uuid",("making new numberspace")); } } uuid_time=tv; mysql_mutex_unlock(&LOCK_uuid_generator); uint32 time_low= (uint32) (tv & 0xFFFFFFFF); uint16 time_mid= (uint16) ((tv >> 32) & 0xFFFF); uint16 time_hi_and_version= (uint16) ((tv >> 48) | UUID_VERSION); str->realloc(UUID_LENGTH+1); str->length(UUID_LENGTH); str->set_charset(system_charset_info); s=(char *) str->ptr(); s[8]=s[13]='-'; tohex(s, time_low, 8); tohex(s+9, time_mid, 4); tohex(s+14, time_hi_and_version, 4); strmov(s+18, clock_seq_and_node_str); DBUG_EXECUTE_IF("force_fake_uuid", strmov(s, "a2d00942-b69c-11e4-a696-0020ff6fcbe6"); ); return str; }