Part 0. 场景描述:
1. 基于 PHP 7.0.x 的项目部署于 CentOS 7.2(1511)系统下,程序通过 PDO 访问远程的 MySQL 5.7.x 数据库系统;
2. 程序在尝试向数据库中 Insert 一条数据时,提示某个 bigint 类型的字段异常,SQL STATE 22003 :
[2018-08-12 16:26:02] production.ERROR: SQLSTATE[22003]: Numeric value out of range: \
1264 Out of range value for column 'mem_id' at row ......
3. 尝试在 MySQL 数据库服务器本地通过 MySQL Client 执行同样的 SQL 语句,执行成功,说明问题发生在部署项目的应用服务器一端。
Part I. 对比分析
通过 phpinfo() 对比了一下新环境和开发环境的具体参数,发现由于升级到了 CentOS 7.2 系统,编译 PHP 7.0.x 时,参数 --with-pdo-mysql 使用默认值的情况下,生成的 pdo_mysql 的 API 版本变更为 5.5.56-MariaDB,而非 MySQL 原生的 API 版本。
猜测问题可能是由于这个 API 版本变更而导致的。
pdo_system.PNGPart II. 使用原生 PDO 驱动重新编译 PHP
1. 重新编译 PHP 7.0.x ,MySQL 驱动相关参数强制指定使用原生驱动;
./configure \
......
--with-mysqli=mysqlnd \
--with-pdo-mysql=mysqlnd \
......
make
make install
2. 重新编译 PHP 后,通过 phpinfo() 确认 pdo_mysql 的 API 版本;
pdo_mysqlnd.PNG3. 重新通过程序执行了对数据库的 Insert 操作,显示执行成功。
Part III. 总结
1. PHP 编译参数中的 mysqlnd,nd 就是 Native Driver 的缩写,即所谓的官方原生驱动;
2. 为了降低操作系统差异造成的业务系统异常,建议编译 PHP 的过程中强制指定使用官方原生驱动,而非使用操作系统自带的驱动;
3. 本例中 PDO 产生的 SQLSTATE[22003] 异常,基本上还是属于特定版本 API 的 BUG 。
EOF
网友评论