MySQL-使⽤UUID_SHORT()的问题
MySQL-使⽤UUID_SHORT( ) 的问题
⽂章⽬录
问题说明
表app_msg的主键id 设置的类型为:bigint 20
使⽤插⼊语句:INSERT INTO app_msg(id,...) VALUES (UUID_SHORT(),...)mysql下载32位
然⽽系统报错:[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 ⼩杭 ε=(´ο`*)))唉