Существующие ответы полезны, но пропущены фрагменты истории.
Вы говорите, что хотите заблокировать базу данных, выполнить несколько запросов, а затем разблокировать ее .
Если вы делаете это, потому что вы не хотите, чтобы какой-либо другой процесс считывал базу данных, в то время как ваши изменения выполнены только частично, вы должны знать, что в SQLite есть функция, которая делает это ненужным: транзакции .
С транзакциями вы можете быть уверены, что никакой другой процесс не увидит ваши изменения, пока они не будут завершены, , но вам не нужно блокировать базу данных, пока вы их делаете . Фактически, пока вы вносите свои изменения, другие процессы могут по-прежнему считывать части базы данных, с которой вы работаете, и другие процессы, база данных будет продолжать выглядеть так же, как и до начала ваших изменений .
Как совершить транзакцию?
- Отправка
BEGIN TRANSACTION
в базу данных.
- Отправьте ваши запросы.
- Отправка
COMMIT
в базу данных (в качестве альтернативы база данных примет COMMIT TRANSACTION
или даже END TRANSACTION
в качестве синонимов).
Как происходит это волшебство?
Пока транзакция открыта, система базы данных не записывает ваши изменения обратно в оперативную базу данных, а записывает их в отдельную область памяти и / или диска. Пока это происходит, другие процессы могут свободно читать из базы данных, и они будут видеть базу данных без каких-либо ваших частичных изменений. После завершения транзакции система базы данных перепишет все ваши изменения в основную базу данных.
Технические детали этого различаются в разных базах данных, но все базы данных, поддерживающие транзакции, будут поддерживать эквивалентную функциональность, которая гарантирует, что другие процессы не увидят ваши незавершенные изменения.
Ваша проблема с другими процессами с ошибками
Даже если другие процессы могут продолжать читать базу данных, пока вы выполняете транзакцию, они все равно не смогут записывать в нее, и в конце вашей транзакции все равно будет очень небольшое время, в которое они будут иметь ждать либо читать, либо писать. Когда они попытаются это сделать, они заметят, что база данных заблокирована .
Это нормально. К сожалению, реализация SQLite3 в PHP (через PDO и класс SQLite3) не ждет получения блокировки, она просто останавливается с ошибкой. Такое поведение по умолчанию будет приемлемым, если вы когда-либо ожидаете, что только один клиент будет одновременно обращаться к базе данных, но неприемлемо в общей среде, такой как веб-сервер.
Итак, при открытии соединения SQLite3 вы всегда должны устанавливать время ожидания. В PHP 5.3.3 вы можете сделать это с помощью метода busyTimeout () SQLite3, но если у вас по какой-то причине нет доступа к нему, вы можете сделать это с помощью следующего SQL-запроса:
PRAGMA busy_timeout = 15000
Это в миллисекундах, так что это 15 секунд. Это должно работать независимо от вашей версии PHP и от того, используете ли вы класс PDO или SQLite3.