Задать вопрос
kay
@kay

Ошибка sqlite3 в php?

Периодически (раза два-три в сутки) возникает Warning:


PHP Warning: SQLite3::query(): Unable to execute statement: database is locked in /bla/bla.php on line bla


Скрипт выполнятеся каждые 10 минут, другие скрипты к базе sqlite3 доступа не имеют. В чем может быть проблема?
  • Вопрос задан
  • 5615 просмотров
Подписаться 2 Оценить Комментировать
Пригласить эксперта
Ответы на вопрос 4
colonel
@colonel
Разработчик PHP, Laravel
Значит сам этот скрипт и лочит базу.
Обычно в таких случаях делается проверка на завершение предыдущего запуска скрипта.
То-есть скрипт не должен запуститься повторно, если предыдущий запуск еще не отработал.
Ответ написан
Комментировать
kay
@kay Автор вопроса
ls -lah db.db
-rw-r--r-- 1 user user 5,0K 2012-04-24 18:40 db.db

Данных мало, но теоретически скрипт может долго держать открытой БД. Странно, что с sqlite2 такого не было, появилось при переходе на sqlite3.
Ответ написан
А вы вообще соединение с базой данных закрываете? о_О
Ответ написан
Mithgol
@Mithgol
По адресу http://www.php.net/manual/en/pdo.begintransaction.php в комментариях 11 апреля 2009 года один субьект рекомендовал в таких случаях сперва создавать подготовленные выражения (что ещё не требует открытия доступа к базе), затем вызывать beginTransaction(), а весь кусок кода обернуть в trycatch внутри while(…){…} и так ловить заблокированность базы:

<?php
$conn = new PDO('sqlite:C:\path\to\file.sqlite');
$stmt = $conn->prepare('INSERT INTO my_table(my_id, my_value) VALUES(?, ?)');
$waiting = true; // Set a loop condition to test for
while($waiting) {
    try {
        $conn->beginTransaction();
        for($i=0; $i < 10; $i++) {
            $stmt->bindValue(1, $i, PDO::PARAM_INT);
            $stmt->bindValue(2, 'TEST', PDO::PARAM_STR);
            $stmt->execute();
            sleep(1);
        }
        $conn->commit();
        $waiting = false;
    } catch(PDOException $e) {
        if(stripos($e->getMessage(), 'DATABASE IS LOCKED') !== false) {
            // This should be specific to SQLite, sleep for 0.25 seconds
            // and try again.  We do have to commit the open transaction first though
            $conn->commit();
            usleep(250000);
        } else {
            $conn->rollBack();
            throw $e;
        }
    }
}
?>
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы