MySQL本地BIGINT字段存为INT最大值2147483647问题排查
问题根源与解决办法
这个问题的核心其实不在MySQL,而在PHP的整数类型处理差异,我来给你拆解清楚:
为什么会出现截断?
- 首先,你的本地环境大概率是32位PHP,而远程服务器是64位PHP。PHP在32位系统下的
PHP_INT_MAX是2147483647(也就是普通INT的最大值),64位系统下则是9223372036854775807(和MySQL BIGINT的最大值完全一致)。 - 当你用
json_decode解析包含超大数值(比如1599757792260458963)的JSON时,32位PHP会因为数值超过PHP_INT_MAX,自动将其保留为字符串类型;而64位PHP能直接解析为合法的大整数。 - 接下来你用
%d格式化这个字符串时,PHP会尝试把它强制转换为int类型。在32位环境下,超过PHP_INT_MAX的数值会被截断到PHP_INT_MAX(也就是2147483647)——MySQL只是接收了PHP传过来的截断后的值,和它本身的BIGINT支持毫无关系。
快速验证方法
你可以在本地执行这段代码确认环境差异:
echo PHP_INT_MAX; // 32位环境输出2147483647,64位输出9223372036854775807 $json = '{"cursor":1599757792260458963}'; $data = json_decode($json); var_dump($data->cursor); // 32位下是string类型,64位下是int类型
可行的解决办法
1. 升级到64位PHP(最彻底)
如果你的服务器环境允许,直接换成64位PHP版本。这样json_decode会自动把大数值解析为整数,%d格式化也不会溢出,插入BIGINT字段完全正常。
2. 改用预处理语句插入(无需更换PHP)
如果暂时无法升级PHP,不要用%d格式化字符串类型的大数值,而是用PHP的数据库扩展(PDO或mysqli)的预处理语句,直接把字符串传入参数,让MySQL自己处理字符串到BIGINT的转换,从根源避免PHP端的截断:
// PDO示例 $pdo = new PDO('mysql:host=localhost;dbname=your_db', 'user', 'pass'); $stmt = $pdo->prepare("UPDATE your_table SET friends_cursor = ?, followers_cursor = ? WHERE id = ?"); $stmt->execute([$friends_cursor_str, $followers_cursor_str, $user_id]);
这种方式既安全,又能避免类型转换带来的溢出问题。
3. 显式指定json_decode的大整数处理
如果你需要主动保留字符串类型,可以在json_decode时加上JSON_BIGINT_AS_STRING选项,确保返回的是字符串,然后直接传入数据库(同样建议配合预处理语句):
$data = json_decode($json, false, 512, JSON_BIGINT_AS_STRING);
补充说明
MySQL 5.7.22本身对BIGINT(20)的支持是完全正常的,它能存储到9223372036854775807的数值。你遇到的问题完全是PHP端的类型转换溢出导致的,和MySQL无关。
内容的提问来源于stack exchange,提问作者PerceptualRobotics
相关产品推荐
相关产品推荐

