天天看點

java short uuid_MySQL-使用UUID_SHORT( ) 的問題

問題說明

表app_msg的主鍵id 設定的類型為:bigint 20

使用插入語句:INSERT INTOapp_msg(id,...) VALUES (UUID_SHORT(),...)

然而系統報錯:[Err] 1264 - Out of range value for column 'id' at row 1

在測試環境使用時沒有問題,但是在準生産資料庫使用時報錯了

簡單分析解決

分析

在兩個資料庫檢視UUID_SHORT()生成的情況:

select UUID_SHORT()

--結果1:26047177025388691 這裡生成了17位的UUID_SHORT

--結果2:18040425909390934036 這裡生成了20位的UUID_SHORT

結果1為17位沒問題,結果2位20位導緻報錯的時候超過最大值

解決

這裡可以知道原因是在字段類型上面,bigint 20 對應的類型是 long long 類型 【長度為:(-2^63 ~ 2^63-1) 10^18 19位數字】;

而UUID_SHORT() 傳回的是 unsigned long long 類型【長度為:(0 ~ 2^64-1) 10^19 20位數字】

是以,原因是在MySQL設定的時候沒有勾選無符号**這個選項導緻的,勾選上就解決了。╮(╯▽╰)╭ 就是這麼的簡單的地方。

臨時解決方式,使用時間錯手動生成了一個19位以内的随機id:

FLOOR(REPLACE(unix_timestamp(current_timestamp(3)),'.',''))*10000+FLOOR(RAND()*10000)

認真查了一些詳細的資料

官方資料

版本:MySQL 5.7

UUID_SHORT()

将“ 短 ”通用辨別符作為64位無符号整數傳回。傳回的值 UUID_SHORT()與UUID()函數傳回的字元串格式128位辨別符 不同,并且具有不同的唯一性屬性。UUID_SHORT()如果滿足以下條件,則保證值 是唯一的:

在server_id目前伺服器的值介于0和255之間,您的設定主從伺服器中是唯一的

您不會在mysqld restarts 之間設定伺服器主機的系統時間

UUID_SHORT()在mysqld重新開機 之間, 你平均每秒調用的次數少于1600萬次

該UUID_SHORT()傳回值的構造是這樣的:

(server_id & 255) << 56

+ (server_startup_time_in_seconds << 24)

+ incremented_variable++;

mysql> SELECT UUID_SHORT();

-> 92395783831158784

UUID_SHORT() 不适用于基于語句的複制。

按照以上官方的說法,UUID_SHORT傳回的值為64位無符号整數,也就是unsigned long long類型。而且,由于使用到了時間搓,這個的初始值會很大(通常都會到17位數字)。

但是,這并不保證其不會傳回18,19,20位的資料,隻能保證在2^64-1以内(最大達到20位數字);

目前沒有查到說可以調整或初始設定UUID_SHORT() 的配置

2019-04-04 小杭 ミ(・・)ミ

補充BUG-Java資料接收錯誤

在資料庫使用了無符号bigint類型之後,使用UUID_SHORT()進行生産id的時候,資料庫是可以插入,沒有問題的。

但是,由于使用的是JAVA的Long類型進行資料接收,這裡有可能是會超出長度的。【資料為無符号long類型這裡差了1位】

因為,JAVA本身的基本類型是不支援無符号類型的,是以這裡的轉換會有問題。

而且,由于是已經遇到了,上面開始的那個BUG,這裡是肯定是會超出的。【UUID_SHORT的值是在mysql啟動的時候自動配置的,是以相當的無奈╮(╯_╰)╭】

是以這裡,特别說明記錄一下,這個問題。

解決辦法:目前還是使用 【自定義的ID生成】,或者 上面 的臨時解決方式【時間戳拼接】

其實最好的還是使用32位的UUID比較的好

2019-04-16 小杭 ε=(´ο`*)))唉