База данных заблокирована при попытке доступа из скрипта PHP - PullRequest
6 голосов
/ 26 марта 2012

Я пишу приложение для Android, которое взаимодействует с бэкэндом PHP. Внутренняя база данных - SQLite 3. Проблема в том, что я периодически получаю эту ошибку PHP Warning: SQLite3::prepare(): Unable to prepare statement: 5, database is locked. Я открываю соединение с базой данных в каждом файле PHP и закрываю его, когда скрипт завершается. Я думаю, проблема в том, что один скрипт заблокировал файл базы данных во время записи в него, а второй пытался получить к нему доступ, что не удалось. Один из способов избежать этого - разделить соединение между всеми скриптами php. Мне было интересно, есть ли другой способ избежать этого?

Edit: Это первый файл:

<?php
$first = SQLite3::escapeString($_GET['first']);
$last = SQLite3::escapeString($_GET['last']);
$user = SQLite3::escapeString($_GET['user']);
$db = new SQLite3("database.db");
$insert = $db->prepare('INSERT INTO users VALUES(NULL,:user,:first,:last, 0 ,datetime())');
$insert->bindParam(':user', $user, SQLITE3_TEXT);
$insert->bindParam(':first', $first, SQLITE3_TEXT);
$insert->bindParam(':last', $last, SQLITE3_TEXT);
$insert->execute();
?>

Вот второй файл:

<?php
$user = SQLite3::escapeString($_GET['user']);
$db = new SQLite3("database.db");
$checkquery = $db->prepare('SELECT allowed FROM users WHERE username=:user');
$checkquery->bindParam(':user', $user, SQLITE3_TEXT);
$results = $checkquery->execute();
$row = $results->fetchArray(SQLITE3_ASSOC);
print(json_encode($row['allowed']));
?>

Ответы [ 2 ]

18 голосов
/ 26 марта 2012

Во-первых, когда вы закончили с ресурсом, вы всегда должны его закрывать.Теоретически он будет закрыт, когда будет собираться мусор, но вы не можете полагаться на то, что PHP сделает это сразу.Я видел несколько баз данных (и других видов библиотек в этом отношении), заблокированных из-за того, что я явно не высвобождаю ресурсы.

$db->close();
unset($db);

Во-вторых, Sqlite3 дает вам время ожидания.Я не уверен, какое значение по умолчанию, но если вы готовы подождать несколько секунд, пока блокировка не будет снята при выполнении запросов, вы можете сказать об этом.Тайм-аут в миллисекундах.

$db->busyTimeout(5000);
5 голосов
/ 23 мая 2017

Я постоянно блокировал базу данных, пока не обнаружил, что некоторые функции sqlite3 должны быть настроены с помощью специальных инструкций SQL (т.е. с использованием ключевого слова PRAGMA). Например, что, по-видимому, решило мою проблему с «базой данных заблокировано», было установить для journal_mode значение «wal» (по умолчанию это «delete», как указано здесь: https://www.sqlite.org/wal.html (см. Активация и настройка режима WAL)).

Итак, в основном мне нужно было создать соединение с базой данных и установить journal_mode с помощью оператора SQL. Пример:

<?php
  $db = new SQLite3('/my/sqlite/file.sqlite3');
  $db->busyTimeout(5000);
  // WAL mode has better control over concurrency.
  // Source: https://www.sqlite.org/wal.html
  $db->exec('PRAGMA journal_mode = wal;');
?>

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...