【问题标题】:segfault with unixODBC (DB2) + PHP + CentOSunixODBC (DB2) + PHP + CentOS 的段错误
【发布时间】:2012-06-11 06:45:21
【问题描述】:

经过 2 天的战斗,我尝试在这里寻求帮助。我正在使用 unixODBC (2.2.11) 在 CentOS 5.4 服务器上使用 DB2 (iSeries) 和 PHP (5.3)。我猜是因为 PHP 从 5.1 升级到 5.3,我让 PHP 在某些查询上出现段错误。经过一番调查,我发现问题出现在一些长字符字段的查询中,例如这张表:

TABLE (
    CONTRACTID  NUMERIC,
    SOMETEXT    CHAR(583)
)

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

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);

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

顺便说一句,我用更新的 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);

所以问题更多地与 PDO 相关,知道吗?

【问题讨论】:

    标签: php pdo segmentation-fault centos unixodbc


    【解决方案1】:

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

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

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

    [ODBC]
    Trace=yes
    TraceFile=/tmp/unixodbc.log
    

    为有问题的列查找对 SQLBindCol 或 SQLGetData 的调用。如果这不能让您到达任何地方,您可以尝试在此处粘贴它的结尾,我会看看它。

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

    【讨论】:

      【解决方案2】:

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

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

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

      【讨论】:

      • 我也遇到了这个问题 - Ubuntu 11.04/PHP 5.3.5 产生了这个问题,而 openSUSE 12.1/PHP 5.3.15 工作正常。我认为这是 PHP 版本,但我仍在研究 php-odbc。您是否找到了不使用合并的解决方法?
      • 可以确认,它适用于 5.3.10 版本的 php 32。它已在 php 5.4 中修复,这里是相关的错误 bugs.php.net/bug.php?id=61387
      【解决方案3】:

      我在带有 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

      使用风险自负!

      【讨论】:

      • 同样的问题,但在 Ubuntu 16.04 上。 strace 向我展示了这个问题。已解决sudo apt-get install unixodbc-dev
      猜你喜欢
      • 2010-09-14
      • 1970-01-01
      • 1970-01-01
      • 2013-05-30
      • 2016-03-25
      • 2017-11-01
      • 2017-01-18
      • 2021-08-21
      • 1970-01-01
      相关资源
      最近更新 更多