Apache/PHP/FreeTDS中的特殊字符不一致,但命令行中没有PHP/FreeTDS

car*_*reo 5 php apache utf-8 freetds

我有两个相同的服务器(称为测试和生产)与Linux红帽企业Linux服务器版本6.2(圣地亚哥),PHP版本5.4.2,Apache Apache 2.4.2,OpenSSL/0.9.8s,freeTDS 0.92-dev(不是最好的)但我暂时无法改变这一点),以及一个单独的Windows服务器与Microsoft SQL Server.

我有一个名为testfs1.php的PHP脚本,它从数据库中读取一个字符串,总是相同的,并打印长度:没有别的.当然,最初的情况要复杂得多,但我还是努力简化.

数据库字段是NVARCHAR,所有组件都设置为使用UTF-8.

通常一切正常:脚本显示预期的字符串长度.但是每隔几个小时甚至几天,只在生产服务器上(主持几个使用频繁的应用程序),错误"激活":Web服务器开始显示从数据库中提取的特殊字符错误.有时候,这个错误会在几分钟后自动"停用"; 上次,它持续了几个小时,然后我跑了

service httpd restart
Run Code Online (Sandbox Code Playgroud)

并且停用了错误.

在错误处于活动状态的时间范围内,它是一致的:对页面testfs1.php的所有Web服务器请求都显示错误的结果; 但是,当我手动运行时

php testfs1.php
Run Code Online (Sandbox Code Playgroud)

在服务器的命令行上,即使它处于活动状态,也不会出现错误.

这是我日夜运行的Bash脚本,用于监控错误的激活:

#!/bin/bash

while : ; do
    echo -n `date +%H%M%S`
    wget https://www.mydomain.org/testfs1.php -o /dev/null
    echo -n "("
    cat testfs1.php
    echo -n ") "
    rm testfs1.php
    sleep 2
done
Run Code Online (Sandbox Code Playgroud)

我用来重现问题的PHP脚本:

<?php
$Conn = mssql_connect( 'PROD', 'user', 'password' ) ;
mssql_select_db( "DBPROD", $Conn ) ;
$Ret = mssql_query( "SELECT lname FROM people WHERE people_key=123", $Conn ) ;
list( $s ) = mssql_fetch_row( $Ret ) ;
print strlen( $s ) ;

?>
Run Code Online (Sandbox Code Playgroud)

这是freeTDS使用的locales.conf:

[default]
    date format = %b %e %Y %I:%M:%S:%z%p
    language = us_english
    charset = UTF-8

[en_US]
    date format = %b %e %Y %I:%M:%S:%z%p
    language = us_english
    charset = UTF-8

[es_ES]
    date format = %b %e %Y %I:%M:%S:%z%p
    language = us_english
    charset = UTF-8

[pt_BR]
    date format = %b %e %Y %I:%M:%S:%z%p
    language = us_english
    charset = UTF-8

[it_IT]
    date format = %b %e %Y %I:%M:%S:%z%p
    language = us_english
    charset = UTF-8
Run Code Online (Sandbox Code Playgroud)

这个问题最令人费解的特点总结:

  1. 当脚本从命令行使用PHP运行时,从不会发生错误,只能从Apache运行
  2. Bug在不同时刻"激活",每隔几小时或几天激活一次,并自行"停用"或使用"service httpd restart"
  3. 在freeTDS使用的locales.conf中,缺少行[default]/charset,错误是自发激活和自动停用(每隔几秒)
  4. 当同一服务器上的另一个应用程序使用gettext时,该错误会更频繁地自发激活和停用(每隔几秒钟)

一位同事暗示这可能是一个内存问题,考虑到重新启动Apache可以释放内存,并解释为什么它不会发生在流量最小的测试服务器上.我不相信.

您能想象出可能的原因和解决方案吗?

ris*_*sin 1

坦白说,我不知道是什么造成了这种不一致的工作。但我想建议您将 FreeTDS 和 unixODBC 更改为稳定版本。由于 FreeTDS 缺乏文档和支持。我已经使用 v0.82 很长一段时间了。而且效果很好。

https://gitorious.org/freetds/mars-freetds/source/52e59affc0110c5ddd379ef1e45c4554123f27b5:README#L2

另一种查找问题详细信息的方法是在 testfs1.php 中使用 PDO MsSQL。通过这种方式,如果本机 mssql 扩展对这种不一致有任何影响,您可以更好地解决问题。