使用unixODBC(DB2)+ PHP + CentOS进行段错误

feu*_*eub 2 php pdo centos unixodbc segmentation-fault

经过2天的战斗,我试着在这里寻求帮助.我正在使用unixODBC(2.2.11)在CentOS 5.4服务器上使用DB2(iSeries)和PHP(5.3).我想这是自PHP升级到5.3以来,我在某些查询中得到了PHP段错误.经过一些调查后,我发现问题出现在一些带有长字段的查询中,例如使用此表:

TABLE (
    CONTRACTID  NUMERIC,
    SOMETEXT    CHAR(583)
)
Run Code Online (Sandbox Code Playgroud)

这段简单的代码引发了段错误:

try {
    $conn = new PDO("odbc:".$dsn, $username, $password, array(
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION)
    );
}
catch (Exception $e) {
    echo $e->getMessage();
}

$sql = 'SELECT * FROM LIB.TABLE ';
$stmt = $conn->prepare($sql);
$vals = $stmt->execute();
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
Run Code Online (Sandbox Code Playgroud)

是否有任何列长度限制或unixODBC和/或PHP> = 5.1的错误?这个Web应用程序工作得很好,然后我遇到了这个问题..

顺便说一句,我用更新的64位CentOS 6.2机器测试了unixODBC 2.2.14和PHP 5.3,问题是一样的.

任何帮助非常感谢,

谢谢

法比安

更新: 使用PHP odbc函数,它的工作原理:

$conn = odbc_connect($dsn, $username, $password);
$res = odbc_exec($conn, $sql);
$rows = odbc_fetch_array($res);
Run Code Online (Sandbox Code Playgroud)

所以问题更多地与PDO有关,任何想法?

小智 9

在这里遇到同样的问题.发现64位php-odbc模块在返回具有NULL值的字段时导致seg错误.解决方法是合并可能存在NULL值的每个字段.这不是一个好的解决方案.我正在看php-odbc.c代码,但我无法保证修复.

解决方法:SELECT COALESCE(CHAR(fieldname),'')FROM ...

我想我要用32位版本替换这个服务器.我有其他人工作得很好.


小智 6

我在使用Vertica 6的Centos 6.3和Centos附带的UnixODBC上遇到了类似的问题,PHP只会出现段错误.所以我跑了strace php mytest.php,发现它试图找到并打开/usr/lib64/libodbccr.so.1

但Centos 6.3只有 libodbccr.so.2

因此快速而肮脏的修复是在以下方面执行以下操作: /usr/lib64

ln -s libodbccr.so.2 libodbccr.so.1

使用风险自负!


boh*_*ica 5

我不能说我知道pdo(我不使用它)或unixODBC或DB2驱动程序中的任何问题.我不确定你的电子邮件中你的第一个平台是使用64位版本还是32位版本,但是当微软增加了64位支持时,ODBC发生了变化(参见SQLLEN/SQLULEN和32/64位平台以及64位ODBC).基本上,一些ODBC API的类型从SQLINTEGER更改为SQLLEN,SQLLEN在64位构建中为64位,在32位构建中为32位.但是,由于没有人知道微软会这样做,并且其中一些参数实际上在规范中描述为32位数量,一些ODBC驱动程序编写者已经为这些参数使用32位数量的64位平台构建了ODBC驱动程序.显然,如果你混合使用单向构建的应用程序或驱动程序管理器与另一种方式构建的驱动程序,那么所有地狱都可能会丢失,你很可能会遇到段错误.因此,首先,如果您使用64位二进制文​​件,则需要检查ODBC驱动程序是否已正确构建 - 请与IBM联系.

unixODBC 2.2.11现在已经很老了,我知道问题已经修复但我仍然在广泛使用它,并且在游标库中只有一个小问题.无论如何,你试过2.2.14,问题是一样的.我怀疑它是unixODBC的问题,但这只是基于我对它的丰富经验而不是因为我知道一个事实.

现在,假设您没有陷入上述情况,您可以做很多事情.尝试启用unixODBC中的登录,然后您可以看到正在进行的ODBC调用以及哪一个失败.您也可以从传递的参数中获得线索,了解可能发生的事情.您可以通过将以下内容添加到odbcinst.ini文件来启用日志记录:

[ODBC]
Trace=yes
TraceFile=/tmp/unixodbc.log
Run Code Online (Sandbox Code Playgroud)

查找对相关列的SQLBindCol或SQLGetData调用.如果这不能让你到任何地方,你可以尝试粘贴它的结尾,我会看看它.

如果您可以从命令行运行PHP程序并安装gdb,则可以在gdb下运行它,它将显示问题发生的堆栈转储.只需执行gdb/path/to/php然后键入r myscript.php并输入以运行它,当它出现segfaults时,您可以使用bt(backtrace)命令来显示堆栈.这应该确定哪个代码导致了段错误,虽然它不一定是错误的代码(例如,如果php传递指向10个字节的缓冲区但是谎言并且说它是100个字节,则写入端的代码不是有过错).