Соединение DB2 с PDO выдает общую ошибку -7008 при вставке или удалении - PullRequest
1 голос
/ 26 июня 2019

Мы разрабатываем приложение PHP, которое подключается как к серверу PostgreSQL, так и к серверу IBM i с DB2. Хотя соединение PDO с PGSQL работает просто отлично, соединение с DB2 может быть получено только из таблиц; Попытка вставить или удалить приводит к следующей ошибке:

SQLSTATE[HY000]: General error: -7008 (SQLExecute[4294960288] at /build/php7.0-ltLrbJ/php7.0-7.0.33/ext/pdo_odbc/odbc_stmt.c:260)

Эта ошибка возникает как в нашей среде разработки, так и в производственной среде. Оба сервера Ubuntu (разные версии, но ненамного); Я использую драйвер ODBC для PDO.

Мы попытались подключиться к другим серверам IBM i и другим пользователям, но та же проблема все еще возникает. Можно выбрать, но не вставить. Поиск в коде ошибки не дает никакого полезного результата, и, как видно из самого сообщения об ошибке, он настолько бесполезен, насколько это возможно. Код в SQLExecute, в частности, нигде не появляется, даже ни одного результата (есть результат на странице IBM, но на самом деле это другой код ошибки).

Код довольно прост, но, возможно, там есть какая-то очевидная и явная ошибка.

Тестовый скрипт:

include("DB2.php");
$oDAO = new DAO();
$res = $oDAO->ejecuta("INSERT INTO <Library>.<File> VALUES (1,0,1)");

DAO:

class DAO{
    var $link;

    public function __construct(){
        // función constructora, inicia la conexión

        $this->link = new PDO("odbc:DRIVER={IBM i Access ODBC Driver};SYSTEM=<System>;PROTOCOL=TCPIP",
                            '<user>', '<pass>');
        $this->link->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        $this->link->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
    }

    private function begin()    { $this->link->beginTransaction(); }
    private function rollback() { $this->link->rollBack(); }
    private function commit()   { $this->link->commit(); }

    public function ejecuta($query){
        try{
            $this->begin();
            $oResult = $this->link->query($query);
            if($oResult){
                $bResult = true;
                $this->commit();
            }else{
                $bResult = false;
                $this->rollback();
            }
        }
        catch (Exception $e){
            echo $e->getMessage();
            $bResult = false;
            $this->rollback();
        }
        return $bResult;
    }
}

Честно говоря, у нас нет вариантов, и я уже потратил на это две недели. Нам просто нужно вставить и удалить записи. Так что любая помощь приветствуется.

1 Ответ

3 голосов
/ 26 июня 2019

Симптомы, которые вы описываете, согласуются с попыткой изменить базу данных под контролем фиксации, но без включения ведения журнала.

Существует три распространенных способа решения этой проблемы:

  1. Включите ведение журнала.Это довольно экстремально, так как люди, которые управляют базой данных, должны будут сделать это, и если у них отключено ведение журнала, скорее всего, они либо не знают, как обращаться с журналами, либо не хотят.Но это единственный практический способ полностью контролировать фиксацию на Db2 для i.

  2. Подключение с включенной автоматической фиксацией.Это добавит неявную фиксацию к любым операторам SQL, изменяющим базу данных, выполняемым с этим соединением.По моему опыту, это наиболее распространенный и удобный способ справиться с ситуацией.

  3. Добавьте WITH NC к каждому соответствующему оператору SQL.В принципе, это дает вам контроль за заявлением о том, следует ли приостановить контроль за обязательствами.На практике, если вы думаете о том, чтобы сделать это в первую очередь, у вас, вероятно, не включено ведение журналов, и, таким образом, вам придется делать это для каждого оператора SQL, модифицирующего базу данных.Вот почему большинство людей склоняются к варианту 2.

...