日常工作中遇到的
在日常的工作中,很少用到bigint类型的 ,尤其是无符号的BIGINT类型的.
有一些时候当用到了这个类型.一定要格外小心.
整体业务逻辑:
1,从csv中取出一行数据
2,通过PHP做 一部解析然后插入到数据库
3,最后在前端通过PHP代码提供一组接口.
出现的问题:
有一组id是采用bigint类型存储的,发现有一部分数据没办法被更新或者插入到数据库的数据错误.
排查:
查看数据库数据类型: bigint(20) 无符号
查看csv里面的数值: 20位int型 14XX开头 .
把更新和插入的SQL找出来 发现有很多bigint这一列ID设置成了 9223372036854775807
想到这个数值好像有点不太对劲
上网找资料:
有符号的bigint 最大取值范围 -9223372036854775808 到 9223372036854775807
数据库里面的存储字段是bigint,无符号 最大表示 20位的 18446744073709551615
现象分析完了,那么原因就显而易见, 这个14xx开头的ID 超出了有符号bigint能表示的最大值.
哪里发生了问题?
查看代码 发现在插入数据库前 ,对这一列ID 使用了一个方法 intval(ID)
查PHP手册,intval手册的返回值说明.
返回值
成功时返回 var 的 integer 值,失败时返回 0。 空的 array 返回 0,非空的 array 返回 1。
最大的值取决于操作系统。 32 位系统最大带符号的 integer 范围是 -2147483648 到 2147483647。举例,在这样的系统上, >intval('1000000000000') 会返回 2147483647。64 位系统上,最大带符号的 integer 值是 9223372036854775807。
字符串有可能返回 0,虽然取决于字符串最左侧的字符。 使用 整型转换 的共同规则。
BUG原因:
PHP将无符号bigint转成了有符号的bigint使数据表示范围溢出了.
解决方法:
将intval改成strval . 使用字符串类型拼接数据库字符串. 问题解决.