【问题标题】:odbc_prepare gives Fatal error: Allowed memory size exhaustedodbc_prepare 给出致命错误:允许的内存大小已用完
【发布时间】:2017-06-27 05:14:14
【问题描述】:

我有一个 Debian 服务器(64 位),我想通过 PHP 将它连接到 AS400 的数据库。我已经安装了 IBM i Access for Linux 和 unixodbc。我遵循了本教程:https://www.albertopicado.es/conexion-odbc-con-base-de-datos-db2-en-un-servidor-ibm-iseries/ 虽然它是西班牙语,但您可以看到我遵循的过程。 问题是我可以建立一个简单的连接,例如:

$server= 'DRIVER={DRIVER_NAME};DATABASE=DATABASENAME;SYSTEM=IP;HOSTNAME=IP;PORT=NUMBER_OF_THE_PORT;PROTOCOL=TCPIP;';
$as400= odbc_connect($server, "username", "password");
$as400 ? echo "ok" : echo "ko";

返回“ok”,所以我知道连接已经建立。然后我做了一个简单的odbc_prepare,如下所示:

$query="SELECT * FROM DATABASE.TABLE WHERE ID=1;
$result=odbc_prepare($as400,$query);

这引发了致命错误:允许的内存大小为 1048576000 字节已用尽(尝试分配 140707423584261 字节)。

我已将 php.ini 文件上的 memory_limit 的值增加到 1000M,但它仍然抛出相同的错误。我一直在网上冲浪,发现有人在使用 64 位版本时遇到问题,例如这篇文章:Linux odbc Fatal error: Allowed memory size,但我正在执行的查询没有任何空值。

信息

odbcinst -j 命令:

DRIVERS............: /usr/local/etc/odbcinst.ini
SYSTEM DATA SOURCES: /usr/local/etc/odbc.ini
FILE DATA SOURCES..: /usr/local/etc/ODBCDataSources
USER DATA SOURCES..: /root/.odbc.ini
SQLULEN Size.......: 8
SQLLEN Size........: 8
SQLSETPOSIROW Size.: 8

odbcinst.ini:

[iSeries Access ODBC Driver]
Description=iSeries Access for Linux ODBC Driver
Driver=/opt/ibm/iSeriesAccess/lib64/libcwbodbc.so
Setup=/opt/ibm/iSeriesAccess/lib64/libcwbodbcs.so
NOTE1=If using unixODBC 2.2.11 or later and you want the 32 and 64-bit ODBC drivers to share DSN's,
NOTE2=the following Driver64/Setup64 keywords will provide that support.
Driver64=/opt/ibm/iSeriesAccess/lib64/libcwbodbc.so
Setup64=/opt/ibm/iSeriesAccess/lib64/libcwbodbcs.so
Threading=2
DontDLClose=1
UsageCount=2

[iSeries Access ODBC Driver 64-bit]
Description=iSeries Access for Linux 64-bit ODBC Driver
Driver=/opt/ibm/iSeriesAccess/lib64/libcwbodbc.so
Setup=/opt/ibm/iSeriesAccess/lib64/libcwbodbcs.so
Threading=2
DontDLClose=1
UsageCount=1

odbc.ini 为空白。

编辑

看到 iSeriesAccess Driver x64 可能有一些错误,我最终将其卸载。然后我安装了 iSeriesAccess 驱动程序 x32。在安装新驱动之前,我创建了我的 Debian multiarch 并下载了 ia32-libs(因为 iSeriesAccess Driver x32 缺少一些软件包)。

使用新的驱动程序我得到另一个错误:
警告:odbc_connect():SQL 错误:[unixODBC][Driver Manager]Can't open lib '/opt/ibm/iSeriesAccess/lib/libcwbodbc.so':找不到文件,SQLConnect 中的 SQL 状态为 01000。

我已经仔细检查了库“libcwbodbc.so”是否存在。我还对 lib 运行命令 ldd 以查看是否缺少某些内容:

linux-gate.so.1 (0xf7763000)
libcwbcore.so => /opt/ibm/iSeriesAccess/lib/libcwbcore.so (0xf7557000)
libodbcinst.so.1 => /usr/lib/i386-linux-gnu/libodbcinst.so.1 (0xf7544000)
libdl.so.2 => /lib/i386-linux-gnu/i686/cmov/libdl.so.2 (0xf753e000)
libpthread.so.0 => /lib/i386-linux-gnu/i686/cmov/libpthread.so.0 (0xf7522000)
libstdc++.so.6 => /usr/lib/i386-linux-gnu/libstdc++.so.6 (0xf7430000)
libm.so.6 => /lib/i386-linux-gnu/i686/cmov/libm.so.6 (0xf73ea000)
libgcc_s.so.1 => /lib/i386-linux-gnu/libgcc_s.so.1 (0xf73cd000)
libc.so.6 => /lib/i386-linux-gnu/i686/cmov/libc.so.6 (0xf721f000)
librt.so.1 => /lib/i386-linux-gnu/i686/cmov/librt.so.1 (0xf7216000)
libltdl.so.7 => /usr/lib/i386-linux-gnu/libltdl.so.7 (0xf720a000)
/lib/ld-linux.so.2 (0xf7766000)

如您所见,没有缺少库。我错过了什么?

解决方案

最后,我安装了 32 位版本的 Debian。在我看来,问题依赖于 64 位版本的 IBM I Access 驱动程序。我只是在新安装上遵循相同的步骤,它就像一个魅力。希望它可以帮助别人。

【问题讨论】:

  • 您使用的是什么 PHP 版本? (我不知道这是否相关,但如果您遇到特定的已知问题,指定它可能会有所帮助)
  • 我使用的是 PHP 5.6.29
  • 当您尝试发布的链接中的建议时发生了什么?编辑问题以显示尝试过的内容和结果。

标签: php ibm-midrange unixodbc


【解决方案1】:

这是 #21286589 的副本。仅仅因为您没有 NULL 值并不意味着您在使用不匹配的 ABI 时不会遇到问题。

这里的问题是老驱动只设置了64位指标值的32位,而PHP读取整个64位。这里 PHP 看到的值为 140707423584261,即十六进制的0x7FF900000005。您可以看到最后 4 个字节是0x00000005,它是 5,应该是返回的实际数据的长度。其余的都是垃圾,因为驱动程序没有更改这些字节。

正如我在回答 Linux odbc Fatal error: Allowed memory size 时提到的,您需要从 IBM i Access Client Solutions Linux 应用程序包中获取新的 ODBC 驱动程序。该驱动程序遵循 unixODBC 自 2.2.14 以来使用的完整 64 位 ABI。新的驱动程序包还包含 Debian .deb 包,因此您引用的博客中的几乎所有步骤都不再需要。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-05
    • 1970-01-01
    相关资源
    最近更新 更多