【问题标题】:Linux odbc Fatal error: Allowed memory sizeLinux odbc 致命错误:允许的内存大小
【发布时间】:2017-04-25 18:08:32
【问题描述】:

我目前在使用 AS400(系列 V6R1)和 Debian 之间的 odbc 链接设置 Intranet 时遇到一些问题,我使用 iseriesAccess7.1 odbc 驱动程序 64 位、unixODBC2.3.1 和 php5.4 支持 unixODBC。

我的链接似乎很好,因为我可以使用 isql 命令(它是 unixODBC 的一部分)连接到我的数据库并执行一些 SQL 查询,但是使用 php 脚本读取数据库中的记录是不可能的。 当我尝试在我的 Intranet 上启动一个小脚本时,我收到以下错误:

致命错误:/home/www/imypdo/imypdo.php 第 122 行中允许的内存大小 134217728 字节已用尽(尝试分配 493921239296 字节)

超过 450 Gb !! /var/log/messages 和 /etc/httpd/logs/error_log 中没有任何内容

一个简单的 sql 查询(选择中只有 1 行)会返回一些奇怪的字符(见下文),一旦我再选择 1 或 2 行,就会发生内存大小错误。

[0] => 数组 ([ADHMAR] => AAAAAAA a@YÿŒ4–X 0!ÿŒ4làÿŒ4làÿŒ4!)

我几乎可以肯定这是与 64 位驱动程序相关的问题,因为我已经有另一个 Debian 与此系列相关联,但使用 32 位驱动程序并且它运行良好。 奇怪的是 isql 命令正在运行,而日志文件中没有任何内容...

如果真的是 64 位驱动问题,我如何向 IBM 证明?

任何帮助将不胜感激

谢谢

--------------- 连接类 ------ ------------

private $_bdd = "DSN=db2;",
        $_user = "USERNAME",
        $_pwd = "Password";

private $_con,
        $_isConnected;


public function open_connection(){
    $this->_con = odbc_connect ($this->_bdd, $this->_user, $this->_pwd ) or die("Error Connection") ;
    $this->_isConnected = true;
}

public function close_connection(){
     odbc_close($this->_con);
     $this->_isConnected = false;
}

public function execute($sql){

    if(!($this->_isConnected))
        $this->open_connection();

    #execute sql
    $res = odbc_exec($this->_con, $sql);

    return $res;
}

public function fetchRow($res){

    $row = odbc_fetch_array($res);
    return $row;
}

}

--------------------- 查询脚本 ------------ ------------------

public function getPhoneLogsByDate($startDate, $endDate) {

    $startDate  = date('Ymd', strtotime($startDate));
    $endDate    = date('Ymd', strtotime($endDate));

    $rr = new As400_Model_as400query();

    $rr->open_connection();

    $sql = "select trim(tluser) as USER, trim(tlacct) as CLIENT, trim(concat(concat(concat(concat(concat(concat(substr(trim(tldate),1,4),'-'),substr(trim(tldate),5,2)),'-'),substr(trim(tldate),7,2)),' '), concat(concat(concat(concat(substr( substr(trim(tltime+1000000),2,6),1,2),':'),substr(substr(trim(tltime+1000000),2,6),3,2)),':'), substr(substr(trim(tltime+1000000),2,6),5,2)))) as DATETIME 
            ,trim(concat(concat(concat(concat(concat(concat(concat(concat(concat(concat(trreas,'|'),trsr01),'|'),trsr02),'|'),trsr03),'|'),trsr04),'|'),trsr05)) as REASONS
            ,trim(concat(concat(concat(tnnot1,tnnot2),tnnot3),tnnot4)) as NOTES

            from cabledta.tlogmstr left join cabledta.tlogreas on trnum#=tlnum#  left join cabledta.tlognote on tnnum#=tlnum#
            where tldate>='".$startDate."' and tldate <='".$endDate."'";



    $res = $rr->execute($sql);

    $response = array();


    while ($row = $rr->fetchRow($res)){

        $response[] = array(

                                'userName'      => $row['USER'],
                                'clientNumber'  => $row['CLIENT'],
                                'logDateTime'   => $row['DATETIME'],
                                'logReasons'    => $row['REASONS'],
                                'logNotes'      => utf8_encode($row['NOTES'])

                            );

    }
    $rr->close_connection();

return $response;
}

【问题讨论】:

  • 您能发布您的查询吗?还有你用来创建数据库连接的PHP代码的sn-p?
  • 更新原帖

标签: php linux odbc ibm-midrange


【解决方案1】:

iSeriesAccess for Linux 7.1 ODBC 驱动程序是针对指定 32 位 SQLLEN 的旧版本 unixODBC 编译的。当您的应用程序或中间件(在本例中为 php)针对较新版本的 unixODBC(自 2.2.14 起)编译时,默认情况下将使用 64 位 SQLLEN。由于驱动程序只覆盖数据的前 32 位,因此在这种情况下,任何将 SQLLEN 指针作为参数的 API 调用的结果都是未定义的。

您有两个选择:重新编译 php 并设置 BUILD_LEGACY_64_BIT_MODE (-DBUILD_LEGACY_64_BIT_MODE) 或使用使用 64 位 SQLLEN 的新 IBM i ODBC 驱动程序。您可以在我写的这篇文章中找到有关 IBM i Access Client Solutions Linux 应用程序包中包含的新 ODBC 驱动程序的更多信息:http://www.ibm.com/developerworks/ibmi/library/i-ibmi-access-client-solutions-linux Nick 在上面的评论中引用了该驱动程序。您可以在此处了解如何下载驱动程序:http://iprodeveloper.com/blog/how-do-you-actually-get-access-client-solutions

【讨论】:

    【解决方案2】:

    我会检查(假设它是 64 位驱动程序)驱动程序管理器、应用程序和驱动程序是否同意 sizeof(SQLLEN)。选择是 32 位和 64 位。我相信 IBM 驱动程序允许您通过配置文件进行设置。 unixODBC 2.3 默认使用 sizeof( SQLLEN ) = 64 位构建。我不能说你的应用是如何构建的。

    【讨论】:

    • unixODBC 2.2.14 驱动程序............:/etc/odbcinst.ini 系统数据源:/etc/odbc.ini 文件数据源..:/etc /ODBCDataSources 用户数据源..:/root/.odbc.ini SQLULEN 大小............:8 SQLLEN 大小............:8 SQLSETPOSIROW 大小。:8
    【解决方案3】:

    听起来你正在阅读一个表格,其文本字段的 CCSID 不正确,很可能分配了 65535,这意味着十六进制/二进制。

    因此系统不会尝试为您将 EBCDIC 文本转换为 ASCII。

    正确的答案是将 CCSID 更改为文件中数据的正确值。 37=美国 EBCDIC。当您使用它时,您可以让他们检查/更改系统的默认 CCSID。 WRKSYSVAL QCCSID

    但是,Windows ODBC 驱动程序确实提供了一个设置,即 ForceTranslation(CCSD 65535)。

    查尔斯

    【讨论】:

      【解决方案4】:

      我想通了。

      在 64 位版本中,当返回字段之一为 NULL 时,odbc 会崩溃。 因此,解决方法是在检索查询时替换所有空字段。

      示例:

      从 database.table 中选择 ifnull(tluser,'') 作为 USER

      【讨论】:

      • 这进一步表明它的 sizeof(SQLLEN) 问题,如果驱动程序写入 32 位 -1 并且应用程序期望64位-1,应用程序将看到140735347425279的列长度
      • 如何更改 SQLLEN?
      • 好吧,对于应用程序,检查供应商,或者如果开源则重建,对于驱动程序管理器,使用正确的标志重建。对于驱动,重建开源,或者看供应商是否有不同的版本或驱动是否有一个标志要设置
      • 你能告诉我更改 SQLLEN 的过程吗?
      猜你喜欢
      • 2015-04-22
      • 2023-03-20
      • 2015-09-18
      • 2023-04-03
      • 1970-01-01
      • 1970-01-01
      • 2013-06-14
      • 2017-12-13
      • 1970-01-01
      相关资源
      最近更新 更多