1. 程式人生 >實用技巧 >其它 >2021-05-25

2021-05-25


Mysql函式UUID()產生重複鍵的說明

一、原理分析

UID的全稱是Universally Unique Identifier,中文為通用唯一識別碼,它有5個版本,MySQL中的UUID()返回一個符合UUID版本1的值,版本1是timestamp + MAC 地址,如RFC 4122中所述(https://www.ietf.org/rfc/rfc4122.txt)。該值是一個128位的數字,表示為五個十六進位制數的utf8字串,格式為AAAAA-bbbb-cccc-dddd-EEEE。關於這一點,MySQL的官網也有論述,其地址是https://dev.mysql.com/doc/refman/8.0/en/miscellaneous-functions.html#function_uuid。

MySQL函式uuid()隨機產生數的原理:生成的uuid隨機數是36位的,其中包含32個字元以及4個分隔符(-),例如de7ee642-4322-11e0-85ab-842b2b4a7e75,在實際開發中,常用replace()把“-”去掉。這32個字元中,分為5組。每一組數產生的機制如下:

UUID = time-low "-" 
time-mid "-"
 time-high-and-version "-"
 clock-seq-and-reserved clock-seq-low "-" 
node

1、前三組值是時間戳換算過來的;

2、 第四組值是暫時性保持時間戳的唯一性。只要不重啟伺服器,不變。

3、 第五組值是一個IEE 802的節點標識值,它是空間上唯一的,如果伺服器地址不變,該值不變,

4、對於同一臺機器,第五組值始終不會發生變化;

5、對於第四組,重新啟動之後,會發現第四組的組與未重啟前的值發生變化,

然後一直不變化,只要重新啟動mysqld服務就會發生變化。

所以,在lexus的專案中,在批處理和發生擁塞的情況,前面三組時間戳相同是存在的,就會產生相同的uuid的值。

二、實驗驗證

2021-05-25

三、解決方案

使用MD5函式重新計算,使其不同。

2021-05-25

四、專案中的出現重複值的解決方案

方案1:使用MD5(),見上例

方案2:使用自定義的隨機函式,自定義uuid的第四個版本

CREATE FUNCTION uuid_v4()

RETURNS BINARY(16)

BEGIN

-- Generate 8 2-byte strings that we will combine into a UUIDv4

SET @h1 = LPAD(HEX(FLOOR(RAND() * 0xffff)), 4, '0');

SET @h2 = LPAD(HEX(FLOOR(RAND() * 0xffff)), 4, '0');

SET @h3 = LPAD(HEX(FLOOR(RAND() * 0xffff)), 4, '0');

SET @h6 = LPAD(HEX(FLOOR(RAND() * 0xffff)), 4, '0');

SET @h7 = LPAD(HEX(FLOOR(RAND() * 0xffff)), 4, '0');

SET @h8 = LPAD(HEX(FLOOR(RAND() * 0xffff)), 4, '0');

-- 4th section will start with a 4 indicating the version

SET @h4 = CONCAT('4', LPAD(HEX(FLOOR(RAND() * 0x0fff)), 3, '0'));

-- 5th section first half-byte can only be 8, 9 A or B

SET @h5 = CONCAT(HEX(FLOOR(RAND() * 4 + 8)),

LPAD(HEX(FLOOR(RAND() * 0x0fff)), 3, '0'));

-- Build the complete UUID

RETURN UNHEX(LOWER(CONCAT(@h1, @h2, @h3, @h4, @h5, @h6, @h7, @h8)));

END;;