MySQL JavaScript查询Snowflake ID末尾数字被置0问题排查与修复
嘿,咱们来搞清楚为什么你的Node.js代码里这些Snowflake ID会被舍入,然后解决这个问题!
问题根源
你的问题出在JavaScript的Number类型精度限制上:JavaScript用的是双精度64位浮点数,它只能精确表示小于2^53(也就是9007199254740992)的整数。而你的Snowflake ID是64位的bigint,数值早就超过了这个范围,当mysql客户端把数据库返回的bigint自动转成Number类型时,就会出现精度丢失、末尾数字被舍入的情况。
而MySQL终端直接返回的是字符串形式的数值,自然不会有这个问题。
修复方案
这里有两种简单有效的修复方式,推荐第一种一劳永逸的:
方式一:修改数据库连接配置,让bigint以字符串返回
在创建数据库连接的时候,加上supportBigNumbers: true和bigNumberStrings: true这两个配置项,这样mysql客户端就会把bigint类型的字段转成字符串返回,完全避免精度丢失:
const mysql = require('mysql'); const con = mysql.createConnection({ host: "localhost", user: "root", password: "root", database: "botproject", supportBigNumbers: true, // 开启大数字支持 bigNumberStrings: true // 将大数字转为字符串返回 }); con.connect(function(err) { if (err) throw err; con.query("SELECT id FROM xplevel WHERE id IN (718141588043202731, 294126883694444544, 685325127373553689, 307409641262940160, 478536470081175562);", function (err, result, fields) { if (err) throw err; console.log(result); }); });
这样返回的id就会是和数据库里完全一致的字符串,不会再有舍入问题。
方式二:在SQL查询里显式转换为字符串
如果你不想修改连接配置,也可以在查询语句里把id转成字符串:
SELECT CAST(id AS CHAR) AS id FROM xplevel WHERE id IN (718141588043202731, 294126883694444544, 685325127373553689, 307409641262940160, 478536470081175562);
不过这种方式需要每次查询都手动处理,不如修改配置来得方便。
另外提一句:如果你的项目可以升级到mysql2包(mysql的现代替代库),它对bigint的默认处理更友好,也能避免这个问题,当然上面的配置在mysql2里同样适用。
内容的提问来源于stack exchange,提问作者King TMK
相关产品推荐
相关产品推荐

