Linux odbc Неустранимая ошибка: допустимый объем памяти

В настоящее время у меня есть некоторые проблемы с настройкой интрасети с помощью ссылки odbc между AS400 (iseries V6R1) и Debian. Я использую 64-битный драйвер iseriesAccess7.1 odbc, unixODBC2.3.1 и php5.4 с поддержкой unixODBC.

Моя ссылка кажется хорошей, потому что я могу подключиться к своей базе данных с помощью команды isql (которая является частью unixODBC) и выполнить некоторые запросы SQL, но невозможно прочитать записи в базе данных, используя скрипт php. Когда я пытаюсь запустить небольшой скрипт в своей интрасети, я получаю следующую ошибку:

Неустранимая ошибка: допустимый объем памяти 134217728 байт исчерпан (попытался выделить 493921239296 байт) в /home/www/imypdo/imypdo.php в строке 122

это более 450 Гб! и ничего в /var/log/messages и в /etc/httpd/logs/error_log

Простой запрос sql (только с 1 строкой в ​​select) вернет некоторые странные символы (см. Ниже), и как только я выберу еще 1 или 2 строки, произойдет ошибка размера памяти.

[0] => Массив ( [ADHMAR] => AAAAAAA a@YÿŒ4–X 0! ŸŒ4làÿŒ4làÿŒ4!)

Я почти уверен, что это проблема, связанная с 64-битным драйвером, потому что у меня уже есть другой Debian, связанный с этим iseries, но с 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;
}

}

--------------------------------- Query Script --------------- ---------------

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

4 ответа

Решение

Я понял это.

В 64-битной версии odbc аварийно завершает работу, когда одно из полей возврата равно NULL. Таким образом, обходной путь заключается в замене всех пустых полей при получении запроса.

пример:

выберите ifnull(tluser,'') как ПОЛЬЗОВАТЕЛЬ из database.table

Драйвер ODBC iSeriesAccess для Linux 7.1 был скомпилирован с более старой версией unixODBC, в которой указан 32-битный SQLLEN. Когда ваше приложение или промежуточное программное обеспечение (в данном случае php) скомпилировано с более новой версией unixODBC (начиная с 2.2.14), по умолчанию будет использоваться 64-битный SQLLEN. Поскольку драйвер перезаписывает только верхние 32-битные данные, результаты любого вызова API, который принимает указатель SQLLEN в качестве параметра, в этом сценарии не определены.

У вас есть два варианта: перекомпилировать php с набором BUILD_LEGACY_64_BIT_MODE (-DBUILD_LEGACY_64_BIT_MODE) или использовать новый драйвер ODBC IBM i, который использует 64-битные SQLLEN. Вы можете найти больше информации о новом драйвере ODBC, включенном в пакет прикладных программ Linux i Client Client Solutions Linux, в этой статье, которую я написал: http://www.ibm.com/developerworks/ibmi/library/i-ibmi-access-client-solutions-linux который Ник ссылался в комментарии выше. Вы можете узнать, как загрузить драйвер здесь: http://iprodeveloper.com/blog/how-do-you-actually-get-access-client-solutions

Я бы проверил (учитывая его 64-битный драйвер), что диспетчер драйверов, приложение и драйвер согласовывают размер ( SQLLEN). Выбор 32 и 64 бит. Я считаю, что драйверы IBM позволяют вам установить это через файл конфигурации. По умолчанию unixODBC 2.3 будет собираться с sizeof( SQLLEN) = 64 бита. Как ваше приложение построено, я не могу сказать.

Похоже, вы читаете таблицу, текстовые поля которой имеют неверный CCSID, скорее всего, им присвоено 65535, что означает шестнадцатеричный / двоичный код.

Таким образом, система не пытается перевести текст EBCDIC в ASCII для вас.

Правильный ответ заключается в том, чтобы получить для CCSID правильное значение для данных в файле. 37= EBCDIC США. Пока вы на нем, вы можете попросить их проверить / изменить CCSID системы по умолчанию. WRKSYSVAL QCCSID

Однако драйвер ODBC для Windows предлагает параметр ForceTranslation (из CCISD 65535).

Чарльз

Другие вопросы по тегам