PDO с ошибкой SQLLite (Код: HY000 errorInfo: HY000, 5, база данных заблокирована)

Я получаю сообщение об ошибке Code: HY000 errorInfo: HY000, 5, database is locked при использовании этого кода:

function saveCity($dbname, $city) {
        $SQLLogger = '';
        $city_id = '';

        try {
            // connect to SQLite database
            $dbh = new PDO("sqlite:".$dbname);

            // put city in the database
            $sql = "INSERT INTO Orte (ORT) VALUES (:city);";
            $sth = $dbh->prepare($sql);
            $sth->bindValue(":city", $city, PDO::PARAM_STR);
            if(!$sth->execute()){
                // error handling
                echo "saveCity";
                echo "Could not execute statement.\n";
                echo "errorCode: " . $sth->errorCode () . "\n";
                echo "errorInfo: " . implode(", ", $sth->errorInfo ()) . "\n";
            } else {
                // log SQL statements
                $sql = str_replace(":city", $city, $sql);
                $SQLLogger .= $sql;
            }

            // get id for new created city
            $sql = "SELECT _id FROM Orte WHERE ORT='$city';";
            $sth = $dbh->prepare($sql);
            $sth->execute();
            $res = $sth->fetch();
            $city_id = $res['_id'];

            // close the database connection
            $dbh = null;
            echo "closed";
        } catch(PDOException $e) {
            echo $e->getMessage();
        }

        // write SQL statements into log file
        if(!empty($SQLLogger)) {
            $logfile = "logs/SQLLogger.txt";
            $new_line = chr(10) . chr(13); //ASCI-character for \r\n
            file_put_contents($logfile, $new_line . $SQLLogger, FILE_APPEND);
        }

        return $city_id;
    }

    function saveZIP($dbname, $zip, $city_id) {
        $SQLLogger = '';
        $zip_id = '';

        try {
            // connect to SQLite database
            $dbh = new PDO("sqlite:".$dbname);

            // save zip code in database
            $sql = "INSERT INTO Plzn (Postleitzahl, Ort) VALUES (:zip, :city_id);";
            $sth = $dbh->prepare($sql);
            $sth->bindValue(":zip", $zip, PDO::PARAM_STR);
            $sth->bindValue(":city_id", $city_id, PDO::PARAM_INT);
            if(!$sth->execute()){
                // error handling
                echo "saveZIP";
                echo "Could not execute statement.\n";
                echo "errorCode: " . $sth->errorCode () . "\n";
                echo "errorInfo: " . implode(", ", $sth->errorInfo ()) . "\n";
            } else {
                // log SQL statements
                $sql = str_replace(":zip", $zip, $sql);
                $sql = str_replace(":city_id", $city_id, $sql);
                $SQLLogger .= $sql;
            }

            // get id for new created zip code
            $sql = "SELECT _id FROM Plzn WHERE Postleitzahl='$zip';";
            $sth = $dbh->prepare($sql);
            $sth->execute();
            $res = $sth->fetch();
            $zip_id = $res['_id'];

            // close the database connection
            $dbh = null;    
        } catch(PDOException $e) {
            echo $e->getMessage();
        }

        // write SQL statements into log file
        if(!empty($SQLLogger)) {
            $logfile = "logs/SQLLogger.txt";
            $new_line = chr(10) . chr(13); //ASCI-character for \r\n
            file_put_contents($logfile, $new_line . $SQLLogger, FILE_APPEND);
        }

        return $zip_id;
    }

    function saveZIPCity($dbname, $zip, $city) {
        $SQLLogger = '';
        $zip_id = '';

        try {
            // connect to SQLite database
            $dbh = new PDO("sqlite:".$dbname);

            // check if zip code is already in database
            $zip = $_SESSION['Plzn']['Postleitzahl'];
            $sql = "SELECT * FROM Plzn WHERE Postleitzahl='$zip';";
            $sth = $dbh->prepare($sql);
            $sth->execute();
            $result = $sth->fetch();
            if (!empty($result)){
                // zip code is already there so lets take it
                $zip_id = $result['_id'];
            // zip code isn't in the database, perhaps the city name is?
            } else {
                // check if city is already in database
                $city = $_SESSION['Orte']['ORT'];
                $sql = "SELECT _id FROM Orte WHERE ORT='$city';";
                $sth = $dbh->prepare($sql);
                $sth->execute();
                $result = $sth->fetch();
                if (!empty($result)){
                    // city is in database, lets take it
                    $city_id = $result['_id'];
                    $zip_id = saveZIP($dbname, $zip, $city_id);
                    echo "city exists. save new zip";
                // city is not in database
                } else {
                    $city_id = saveCity($dbname, $city);
                    $zip_id = saveZIP($dbname, $zip, $city_id);
                }
            }
            // close the database connection
            $dbh = null;    
        } catch(PDOException $e) {
            echo $e->getMessage();
        }

        // write SQL statements into log file
        if(!empty($SQLLogger)) {
            $logfile = "logs/SQLLogger.txt";
            $new_line = chr(10) . chr(13); //ASCI-character for \r\n
            file_put_contents($logfile, $new_line . $SQLLogger, FILE_APPEND);
        }

        return $zip_id;
    }

В этом коде я использую отдельные функции, и кажется, что есть проблема параллелизма. Если я помещу все в одну функцию, как здесь:

function saveZIPCity($dbname, $zip, $city) {
    $SQLLogger = '';
    $zip_id = '';

    try {
        // connect to SQLite database
        $dbh = new PDO("sqlite:".$dbname);

        // check if zip code is already in database
        $zip = $_SESSION['Plzn']['Postleitzahl'];
        $sql = "SELECT * FROM Plzn WHERE Postleitzahl='$zip';";
        $sth = $dbh->prepare($sql);
        $sth->execute();
        $result = $sth->fetch();
        if (!empty($result)){
            // zip code is already there so lets take it
            $zip_id = $result['_id'];
        // zip code isn't in the database, perhaps the city name is?
        } else {
            // check if city is already in database
            $city = $_SESSION['Orte']['ORT'];
            $sql = "SELECT _id FROM Orte WHERE ORT='$city';";
            $sth = $dbh->prepare($sql);
            $sth->execute();
            $result = $sth->fetch();
            if (!empty($result)){
                // city is in database, lets take it
                $city_id = $result['_id'];
                // save zip code in database
                $sql = "INSERT INTO Plzn (Postleitzahl, Ort) VALUES (:zip, :city_id);";
                $sth = $dbh->prepare($sql);
                $sth->bindValue(":zip", $zip, PDO::PARAM_STR);
                $sth->bindValue(":city_id", $city_id, PDO::PARAM_INT);
                if(!$sth->execute()){
                    // error handling
                    echo "Could not execute statement.\n";
                    echo "errorCode: " . $sth->errorCode () . "\n";
                    echo "errorInfo: " . implode(", ", $sth->errorInfo ()) . "\n";
                } else {
                    // log SQL statements
                    $sql = str_replace(":zip", $zip, $sql);
                    $sql = str_replace(":city_id", $city_id, $sql);
                    $SQLLogger .= $sql;
                }

                // get id for new created zip code
                $sql = "SELECT _id FROM Plzn WHERE Postleitzahl='$zip';";
                $sth = $dbh->prepare($sql);
                $sth->execute();
                $res = $sth->fetch();
                $zip_id = $res['_id'];
            // city is not in database
            } else {
                // put city in the database
                $sql = "INSERT INTO Orte (ORT) VALUES (:city);";
                $sth = $dbh->prepare($sql);
                $sth->bindValue(":city", $city, PDO::PARAM_STR);
                if(!$sth->execute()){
                    // error handling
                    echo "Could not execute statement.\n";
                    echo "errorCode: " . $sth->errorCode () . "\n";
                    echo "errorInfo: " . implode(", ", $sth->errorInfo ()) . "\n";
                } else {
                    // log SQL statements
                    $sql = str_replace(":city", $city, $sql);
                    $SQLLogger .= $sql;
                }

                // get id for new created city
                $sql = "SELECT _id FROM Orte WHERE ORT='$city';";
                $sth = $dbh->prepare($sql);
                $sth->execute();
                $res = $sth->fetch();
                $city_id = $res['_id'];

                // save zip code in database
                $sql = "INSERT INTO Plzn (Postleitzahl, Ort) VALUES (:zip, :city_id);";
                $sth = $dbh->prepare($sql);
                $sth->bindValue(":zip", $zip, PDO::PARAM_STR);
                $sth->bindValue(":city_id", $city_id, PDO::PARAM_INT);
                if(!$sth->execute()){
                    // error handling
                    echo "Could not execute statement.\n";
                    echo "errorCode: " . $sth->errorCode () . "\n";
                    echo "errorInfo: " . implode(", ", $sth->errorInfo ()) . "\n";
                } else {
                    // log SQL statements
                    $sql = str_replace(":zip", $zip, $sql);
                    $sql = str_replace(":city_id", $city_id, $sql);
                    $SQLLogger .= $sql;
                }

                // get id for new created zip code
                $sql = "SELECT _id FROM Plzn WHERE Postleitzahl='$zip';";
                $sth = $dbh->prepare($sql);
                $sth->execute();
                $res = $sth->fetch();
                $zip_id = $res['_id'];
            }
        }
        // close the database connection
        $dbh = null;    
    } catch(PDOException $e) {
        echo $e->getMessage();
    }

    // write SQL statements into log file
    if(!empty($SQLLogger)) {
        $logfile = "logs/SQLLogger.txt";
        $new_line = chr(10) . chr(13); //ASCI-character for \r\n
        file_put_contents($logfile, $new_line . $SQLLogger, FILE_APPEND);
    }

    return $zip_id;
}

работает без проблем. В чем проблема?

Решение. Используйте класс для выполнения запросов и избегайте одновременного открытия соединения с базой данных.


person testing    schedule 31.01.2012    source источник


Ответы (1)


Я верю в это из-за этой строки

$city_id = saveCity($dbname, $city);
$zip_id = saveZIP($dbname, $zip, $city_id);

В каждом вызове вашей функции. вы инициализируете новое соединение с БД. В этом случае вы используете sqlite, который работает только в том случае, если вы вызываете его только один раз. потому что для этого требуется блокировка записи (вот почему вы получили эту ошибку - вы вызываете ее дважды)

person Rezigned    schedule 31.01.2012
comment
Но разве звонки не должны обрабатываться один за другим? Я также получил ошибку в этой строке $zip_id = saveZIP($dbname, $zip, $city_id); . Я читал, что, возможно, драйвер pdo не поддерживает несколько подготовленных операторов (в случае saveZIP, INSERT и SELECT). - person testing; 31.01.2012
comment
Нет, я так не думаю. Для быстрого теста вы можете поставить $dbh = null в конце каждой функции (перед возвратом) для закрытия PDO соединения, чтобы увидеть, работает ли оно для вас. - person Rezigned; 31.01.2012
comment
Я думаю ты прав. Иначе не было бы проблемы. Тем временем я переключился на класс запроса, и у меня больше нет этой проблемы. Спасибо за помощь. Я проголосовал за вас. - person testing; 31.01.2012