Laravel PDO更新数据溢出,原生PDO没问题
\DB::update("update at_deliver set real_billing_weight_total=?,pre_billing_weight_total=? where id = ?", [
2147483648,
2147483647,
1
]);
上面的两个字段都是 bigint 的,更新后结果 real_billing_weight_total = 0,pre_billing_weight_total=2147483647
$pdo = new PDOConnection($dsn, $user, $password);
$st = $pdo->prepare("update `at_deliver` set `real_billing_weight_total` = ?,pre_billing_weight_total=? where id = ?");
$st->bindValue(1, 2147483647, \PDO::PARAM_INT);
$st->bindValue(2, 4294967296, \PDO::PARAM_INT);
$st->bindValue(3, 1);
$res = $st->execute();
这样自己更新没问题
这个问题只是在指定的服务器上面才会有问题,感觉框架需要在哪里读取服务器的某个配置导致的,但是定位不出来
运维安装的PDO非官方的,导致的问题,已解决
5 Comments
字面上看起来是把2147483648当做溢出处理了,要进一步定位下到底是PHP语言还是MySQL执行环节的问题,比如把真正执行前的完整SQL语句打印出来看看
Laravel底层处理逻辑也是通过PDO进行处理的:
你可以通过
PHP_INT_MAX
查看下系统支持的最大整型数,32位系统肯定不支持bigint
的使用laravel打印出来的sql和绑定都是正确的。但是查mysql的bin_log里面记录的是错误的。系统是64位的,我自己直接使用原生的都是可以保存成功的。
我在这层打印调试,值都是对的。按说这里应该已经是最底层了的。
我再昨天(2019年4月22日)也遇到这个问题了。数据58 0000 0000,58亿,超出了32位整型数据,导致溢出,存入数据库后变成了1505032704,很郁闷。 后来发现用PDO直接保存就没事,是因为Thinkphp在连接的时候设置参数了: // PDO连接参数 protected $params = [ PDO::ATTR_CASE => PDO::CASE_NATURAL, PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_ORACLE_NULLS => PDO::NULL_NATURAL, PDO::ATTR_STRINGIFY_FETCHES => false, PDO::ATTR_EMULATE_PREPARES => false, ]; 注意PDO::ATTR_EMULATE_PREPARES => false,会导致数据溢出,这个是因为php使用了php_mysql扩展,而不是用的php_mysqlnd这个更新的扩展。我的数据库用的Mariadb,所以看到pdo_mysql扩展用的是5.5.60-MariaDB。用yum remove php72w-mysql,再yum install php72w-mysqlnd,重启php-fpm,问题解决! 根本原因还是PDO::ATTR_EMULATE_PREPARES => false导致使用了原生驱动的预处理语句,原生驱动肯定用了int32类型数据!而新版的原生驱动mysqlnd则解决了这个问题。