2012-03-26 7 views
5

Estoy escribiendo una aplicación de Android que se comunica con un back-end PHP. El backend db es SQLite 3. El problema es que recibo este error intermitentemente PHP Warning: SQLite3::prepare(): Unable to prepare statement: 5, database is locked. Estoy abriendo una conexión a la base de datos en cada archivo PHP y cerrándolo cuando termina el script. Creo que el problema es que una secuencia de comandos bloqueó el archivo de la base de datos mientras escribía y la segunda secuencia de comandos intentaba acceder a ella, que falló. Una forma de evitar esto sería compartir una conexión entre todos los scripts php. Me preguntaba si hay alguna otra forma de evitar esto.Base de datos bloqueada al intentar acceder desde el script PHP

Editar: Este es el primer archivo:

<?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(); 
?> 

Aquí es el segundo archivo:

<?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'])); 
?> 
+0

Primero comparta el código –

+0

Código agregado y más descripción –

Respuesta

13

En primer lugar, cuando haya terminado con un recurso que siempre debe cerrarla. En teoría, se cerrará cuando se recoja basura, pero no se puede depender de que PHP lo haga de inmediato. He visto algunas bases de datos (y otros tipos de bibliotecas) cerrarse porque no liberaba recursos explícitamente.

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

En segundo lugar, Sqlite3 le da un tiempo de espera ocupado. No estoy seguro de cuál es el valor predeterminado, pero si está dispuesto a esperar unos segundos hasta que el bloqueo se borre cuando ejecuta las consultas, puede decirlo. El tiempo de espera es en milisegundos.

$db->busyTimeout(5000); 
+0

De hecho, me olvidé de cerrar la conexión. Se agregó eso y 'busyTimeout'. Está funcionando bien ahora. ¡Gracias! –

+3

Aún así, es posible que experimente problemas. Si accede al mismo DB desde un script mientras todavía está abierto desde otro script (Ej: Ajax), entonces tendrá el mismo problema – Alex

+0

El valor predeterminado es 60 segundos == 60000 milisegundos. ¿Cómo 5000 va a hacer algo útil? – TechJS

1

que estaba recibiendo "base de datos bloqueada" todo el tiempo hasta que descubrí algunas características de sqlite3 se debe establecer mediante el uso de instrucciones especiales de SQL (es decir, usando la palabra clave PRAGMA). Por ejemplo, lo que aparentemente resolvió mi problema con "base de datos bloqueada" fue establecer journal_mode en 'wal' (está predeterminado en 'eliminar', como se indica aquí: https://www.sqlite.org/wal.html (ver Activación y configuración del modo WAL)).

Así que, básicamente, lo que tenía que hacer era crear una conexión a la base de datos y configurar el modo_registro con la instrucción SQL. Ejemplo:

<?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;'); 
?> 

Espero que ayude.

Cuestiones relacionadas