我们的一个项目,用了PDO_MYSQL拓展,准备迁移服务器,新环境需要编译安装环境。昨天,运维同事抽空编译了一下,一直编译不上pdo_mysql,同时,公司的一款新webgame临近上线,他们实在太忙,我这个三流运维技术的程序员来试试吧。

运维同事描述:
服务器系统版本:Linux version 2.6.32-71.el6.x86_64 (mockbuild@c6b6.centos.org) (gcc version 4.4.4 20100726 (Red Hat 4.4.4-13) (GCC) ) #1 SMP Fri May 20 03:51:51 BST 2011

编译PHP的参数

查看源代码打印帮助1 ... 

2 tar zxvf $soft_dir/php-5.3.8.tar.gz -C $soft_tmp 

3 cd  $soft_tmp/php-5.3.8 

4  ./configure  --prefix=$soft_install/php --with-config-file-path=$soft_install/php/etc --with-mysql=$soft_install/mysql --with-mysqli=mysqlnd  --with-gd=$soft_install/gd --with-jpeg-dir=$soft_install/jpeg --with-png-dir=$soft_install/png --with-freetype-dir=$soft_install/freetype --enable-bcmath --with-mcrypt  && make && make install

5 ...

之后再次编译 pdo_mysql 拓展

查看源代码打印帮助1 ... 

2 cd $soft_tmp/PDO_MYSQL-1.0.2/ 

3 $soft_install/php/bin/phpize 

4 ./configure --with-php-config=$soft_install/php/bin/php-config  --with-pdo-mysql=$soft_install/mysql/  && make && make install

5 ...

之后, shell里执行 php -i 和 php -m都没有看到 pdo_mysql拓展。搜pdo_mysql,在将路径添加到php.ini中,仍找不到这个扩展,判断为编译失败。

这里是将pdo_mysql作为一个拓展引入使用的。在php5.3中,PHP开发组把mysqlnd作为默认的连接MYSQL的数据库驱动来使用,据官方描述,节省内存40%,速度更快,当然或许是为了解决许可协议的问题。之前PHP连接MYSQL,是调用MYSQL官方提供的C/C++编写的lib_mysql的dll/so,来实现。这个类库同样可以给PYTHON等脚本语言调用,只要按照API规范来。我们改用mysqlnd之后,就不用再为了lib_mysql去安装mysql client了。详情见:mysqlnd插件mysqlnd_ms的介绍。
两种方法都可以,运维同事都尝试了,由于时间关系,他们没做过多的尝试研究,就转向更紧急的项目了。

运维同事下载使用的PDO_MYSQL拓展的地址是 http://pecl.php.net/package/PDO_MYSQL ,里面用很耀眼的颜色,标注如下几行字

This package is not maintained anymore and has been superseded. Package has moved to channel http://svn.php.net/viewvc/php/php-src/trunk/ext/pdo_mysql/, package ext/pdo_mysql.

也就是说,早在2006年5月1(我是根据最后一个打包文件日期猜的,或许不准)之后,PHP已经将这个pdo拓展放到PHP源码的 ext/pdo_mysql下内置了。这里的这个包,将不会在更新维护了。

在PHP官方文档上对pdo_mysql使用mysqlnd的时候,是这么描述的
在php5.3中,已经支持mysqlnd作为数据库连接驱动了。而在将来的php5.4中,将变为默认的连接驱动。如图:



mysqlnd-pdo_mysql


开启这个类库的

查看源代码打印帮助1 ./configure --with-mysql=mysqlnd --with-mysqli=mysqlnd --with-pdo-mysql=mysqlnd

之后,我的编译参数如下

查看源代码打印帮助1 ./configure  --prefix=/usr/local/services/php --with-config-file-path=/usr/local/services/php/etc --with-pdo-mysql=mysqlnd --with-mysql=mysqlnd --with-mysqli=mysqlnd  --with-iconv-dir=/usr/local/services/libiconv --disable-phar --with-gd=/usr/local/services/gd --with-jpeg-dir=/usr/local/services/jpeg --with-png-dir=/usr/local/services/png --with-freetype-dir=/usr/local/services/freetype --enable-bcmath --with-mcrypt

区别是使用php内置的pdo_mysql类库,使用mysqlnd作为连接驱动。

make之后,提示如下错误

查看源代码打印帮助01 soft/soft_tmp/php-5.3.8/ext/mysql/php_mysql.c:1070: undefined reference to `mysql_eof' 

02 /data/sa/suse-soft/soft_tmp/php-5.3.8/ext/mysql/php_mysql.c:1070: undefined reference to `mysql_fetch_row' 

03 ext/mysql/php_mysql.o: In function `zif_mysql_error': 

04 /data/sa/suse-soft/soft_tmp/php-5.3.8/ext/mysql/php_mysql.c:1727: undefined reference to `mysql_error' 

05 ext/mysql/php_mysql.o: In function `zif_mysql_errno': 

06 /data/sa/suse-soft/soft_tmp/php-5.3.8/ext/mysql/php_mysql.c:1758: undefined reference to `mysql_errno' 

07 ext/mysql/php_mysql.o: In function `php_mysql_do_connect': 

08 /data/sa/suse-soft/soft_tmp/php-5.3.8/ext/mysql/php_mysql.c:705: undefined reference to `mysql_get_client_version' 

09 /data/sa/suse-soft/soft_tmp/php-5.3.8/ext/mysql/php_mysql.c:963: undefined reference to `mysql_init' 

10 /data/sa/suse-soft/soft_tmp/php-5.3.8/ext/mysql/php_mysql.c:976: undefined reference to `mysql_options' 

11 /data/sa/suse-soft/soft_tmp/php-5.3.8/ext/mysql/php_mysql.c:980: undefined reference to `mysql_real_connect' 

12 /data/sa/suse-soft/soft_tmp/php-5.3.8/ext/mysql/php_mysql.c:1002: undefined reference to `mysql_options' 

13 /data/sa/suse-soft/soft_tmp/php-5.3.8/ext/mysql/php_mysql.c:706: undefined reference to `mysql_get_client_version' 

14 /data/sa/suse-soft/soft_tmp/php-5.3.8/ext/mysql/php_mysql.c:844: undefined reference to `mysql_init' 

15 /data/sa/suse-soft/soft_tmp/php-5.3.8/ext/mysql/php_mysql.c:850: undefined reference to `mysql_options' 

16 /data/sa/suse-soft/soft_tmp/php-5.3.8/ext/mysql/php_mysql.c:853: undefined reference to `mysql_real_connect' 

17 /data/sa/suse-soft/soft_tmp/php-5.3.8/ext/mysql/php_mysql.c:871: undefined reference to `mysql_options' 

18 /data/sa/suse-soft/soft_tmp/php-5.3.8/ext/mysql/php_mysql.c:989: undefined reference to `mysql_error' 

19 /data/sa/suse-soft/soft_tmp/php-5.3.8/ext/mysql/php_mysql.c:992: undefined reference to `mysql_errno' 

20 /data/sa/suse-soft/soft_tmp/php-5.3.8/ext/mysql/php_mysql.c:898: undefined reference to `mysql_ping' 

21 /data/sa/suse-soft/soft_tmp/php-5.3.8/ext/mysql/php_mysql.c:899: undefined reference to `mysql_errno' 

22 /data/sa/suse-soft/soft_tmp/php-5.3.8/ext/mysql/php_mysql.c:901: undefined reference to `mysql_real_connect' 

23 /data/sa/suse-soft/soft_tmp/php-5.3.8/ext/mysql/php_mysql.c:911: undefined reference to `mysql_options' 

24 /data/sa/suse-soft/soft_tmp/php-5.3.8/ext/mysql/php_mysql.c:862: undefined reference to `mysql_error'

这种错误,让我手足无措,GOOGLE搜了下,也没找到相关案例,而且,一直被墙,打不开国外网页。百度搜的结果,还是算了。(中文还行,E文的话,百度确实不行,尤其是程序相关)
之后,尝试make clean,清除之前的编译结果缓存之类。
再次make,有个小意外

查看源代码打印帮助1 ERROR: invalid PHP executable specified by TEST_PHP_EXECUTABLE  = .....

再次搜索,这倒是很多网友遇到过,大部分的建议就是无视这个错误,不影响编译。照做。make install ,一路挺顺畅。

接着,php -i / php -m 也没发现pdo_mysql模块。
郁闷无比,决定看下web下的phpinfo结果,发现居然有了。问题终于解决了。。。万岁。。

可是!!!
1,为啥php -i 、php -m 的结果里看不到呢? 思考,为什么呢?
结合刚刚的报错,联想到CLI 模式下的php 脚本(以及相关的php.ini)跟刚刚从web下访问的php程序不是同一个。检查环境变量,以及切换到编译好的目录下执行php -i,发现pdo_mysql、mysqlnd等相关添加的模块了。

2,php.ini里没启用pdo_mysql拓展,为什么还能看的到呢?
这次使用的是PHP内置的类库,不是以新拓展方式加载运行的,所以,不用更改php.ini,再添加相关so路径。

综上所述,文章没有高深的东西,只是有几个需要细心的点。
1,以官方文档为准,一切跟着官方文档来,不轻易采信网络上网友提供的编译参数,包括这边博文。不论对方是老手、大牛,还是其他什么什么有威望的人。他们提供的方法或许跟你当前的环境不一致,时间也相差很大,或许相隔好几年了。
2,确认得到的结果是准确的,怎么说呢,文中的例子中php-i的路径不是我们新编译的,而是之前编译,或者yum安装的,一定要到自己编译的程序目录下,用自己新编译的脚本去执行测试,获得测试结果,下结论,不为了偷懒,不敲路径,直接写程序名进行测试。
3,遇到诡异的错误,我总会想要一个全新的系统,进行安装,以确保不被各种冗余、缓存等垃圾文件干扰。例子中用了make clean进行清除相关缓存,来解决文件缓存问题。(感谢@ivon_lee 的帮助)
4,自动安装脚本要及时更新,当然,不是意味着追求最新版本。例子中的pdo_mysql的拓展,官方提供了更好的方式,不论是效率,资源占用,都有更好的提升,为啥不使用呢。