2009-06-08 33 views
9

¿Alguien puede proporcionar alguna entrada sobre este error. Estoy tratando de insertar en la tabla usando Objective C.Excepción SQLite: SQLite ocupado

Mientras hago esto, obtengo un error SQLite ocupado. ¿Por qué está pasando esto?

+0

¿Puede proporcionarnos algún código de ejemplo? Un par de líneas para entender lo que está sucediendo. – stefanB

Respuesta

19

Si obtiene como resultado al invocar una función de sqlite3 la SQLITE_BUSY código de error, esto significa que según lo observado por drdaeman que el PP ha sido bloqueado por el mismo proceso o en un hilo dentro de su proceso.

La forma correcta de manejar esta situación es probar la operación en un bucle, y si el código de retorno sigue siendo SQLITE_BUSY, esperar un tiempo (usted decide el valor de tiempo de espera) y luego volver a intentar la operación en el siguiente iteración de bucle

Por ejemplo, el siguiente fragmento de código se toma de la FMDB Objetivo C envoltorio (http://code.google.com/p/flycode/source/browse/trunk/fmdb) muestra cómo preparar una declaración para una consulta teniendo en cuenta que algunas operaciones pueden volver SQLITE_BUSY:

int numberOfRetries = 0; 
BOOL retry   = NO; 

if (!pStmt) { 
    do { 
     retry = NO; 
     rc  = sqlite3_prepare(db, [sql UTF8String], -1, &pStmt, 0); 

     if (SQLITE_BUSY == rc) { 
      retry = YES; 
      usleep(20); 

      if (busyRetryTimeout && (numberOfRetries++ > busyRetryTimeout)) { 
       NSLog(@"%s:%d Database busy (%@)", __FUNCTION__, __LINE__, [self databasePath]); 
       NSLog(@"Database busy"); 
       sqlite3_finalize(pStmt); 
       [self setInUse:NO]; 
       return nil; 
      } 
     } 
     else if (SQLITE_OK != rc) { 


      if (logsErrors) { 
       NSLog(@"DB Error: %d \"%@\"", [self lastErrorCode], [self lastErrorMessage]); 
       NSLog(@"DB Query: %@", sql); 
       if (crashOnErrors) { 

        NSAssert2(false, @"DB Error: %d \"%@\"", [self lastErrorCode], [self lastErrorMessage]); 
       } 
      } 

      sqlite3_finalize(pStmt); 

      [self setInUse:NO]; 
      return nil; 
     } 
    } 
    while (retry); 
} 

Por el De esta forma, si necesita acceder a sqlite, FMDB es muy útil y mucho más fácil de usar con respecto al acceso directo a través de las API C nativas.

+6

Puedes lograr casi lo mismo simplemente llamando [sqlite3_busy_timeout] (http://www.sqlite.org/c3ref/busy_timeout.html). –

+1

Downvoted. Primero, si alguien está haciendo algo, incluso en algún proyecto de código abierto, eso no implica que sea una "cosa propia". Algo realmente apropiado es algo que los autores de la biblioteca en cuestión declaran en la documentación. http://www.sqlite.org/c3ref/busy_handler.html –

+0

@Alaksiej N: ¿leyó detenidamente la documentación del controlador ocupado que proporcionó en su comentario? Se lee: "La presencia de un controlador ocupado no garantiza que se invocará cuando haya contención de bloqueo. Si SQLite determina que la invocación del controlador ocupado podría resultar en un interbloqueo, continuará y devolverá SQLITE_BUSY o SQLITE_IOERR_BLOCKED en lugar de invocar el controlador ocupado ". Por lo tanto, no hay garantía de que SQLite siempre invoque el controlador ocupado que defina. –

7

Tuve un problema similar con SQLITE_BUSY en los comandos INSERT INTO secuenciales. La primera fila se insertó bien, pero cuando la aplicación intentó insertar una segunda fila, obtuve el estado SQLITE_BUSY. Después de buscar en Google, me enteré de que debes llamar a sqlite3_finalize() en las sentencias después de ejecutarlas: http://www.sqlite.org/c3ref/finalize.html. Al finalizar mis declaraciones solucioné mi problema.

4

En mi caso, había olvidado cerrar la base de datos después de usarla. Después de la mina fija:

sqlite3_finalize(statement); 
sqlite3_close(contactDB); 

FMDB también puede aliviar estos dolores de cabeza de usted fácilmente.

0

Fue tan simple como ejecutar el símbolo del sistema como administrador para mí. Alternativamente, en UNIX, es posible que pueda usar sudo al iniciar la base de datos.