la base de données des erreurs sqlite est verrouillée

j'ai une base de données sqlite dans l'application iPhone que j'écris. J'obtiens une erreur avec le code suivant que j'exécute dans un thread d'arrière-plan. Dans le fil de fond, j'appelle cette méthode:

 - (BOOL) songIsInDatabase:(NSString *)songTitle
{
NSString *docsDir;
NSArray *dirPaths;

dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
docsDir = [dirPaths objectAtIndex:0];


//Build the path to the database file
NSString *databasePath = [[NSString alloc] initWithString:[docsDir stringByAppendingPathComponent:@"Database.db"]];

const char *dbpath = [databasePath UTF8String];

sqlite3_stmt *statement;

if(sqlite3_open(dbpath, &DB) == SQLITE_OK){

    NSString *insertSQL = [NSString stringWithFormat:@"select * from Bpm_Table where song_title = '%@'", songTitle];

    const char *insert_stmt = [insertSQL UTF8String];
    if(sqlite3_prepare_v2(DB, insert_stmt, -1, &statement, NULL) == SQLITE_OK)
    {
        while (sqlite3_step(statement) == SQLITE_ROW)
        {
            return YES;
            break;
        }
    }else{
        NSLog(@"the error is %s", sqlite3_errmsg(DB));
    }
    sqlite3_finalize(statement); 
}

[databasePath release];
return NO;
}

alors j'appelle cette méthode:

- (void) addSongToDatabase: (NSString *) songTitle andBPM: (int)bpm andGenre: (NSString *) genre
{
NSString *docsDir;
NSArray *dirPaths;

dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
docsDir = [dirPaths objectAtIndex:0];


//Build the path to the database file
NSString *databasePath = [[NSString alloc] initWithString:[docsDir stringByAppendingPathComponent:@"Database.db"]];

const char *dbpath = [databasePath UTF8String];

sqlite3_stmt *statement;

if(sqlite3_open(dbpath, &DB) == SQLITE_OK){

    NSString *insertSQL = [NSString stringWithFormat:@"insert or replace into Bpm_Table (song_title, bpm, genre) values ("%@", "%d", "%@")", songTitle, bpm, genre];

    const char *insert_stmt = [insertSQL UTF8String];
    if(sqlite3_prepare(DB, insert_stmt, -1, &statement, NULL) == SQLITE_OK){
        if(sqlite3_step(statement) == SQLITE_DONE)
        {

        } else {
            NSLog(@"error: %s", sqlite3_errmsg(DB));
        }
    }sqlite3_finalize(statement);
}

[databasePath release];
}

si j'exécute ces deux méthodes, l'une juste après l'autre, j'obtiens une erreur qui dit la base de données est verrouillée . J'ai ajouté les déclarations sqlite3_finalize après poking autour de google dans l'espoir que cela réglerait le problème. Si je commente l'une ou l'autre des méthodes, Je ne comprends pas cette erreur.

est-ce que quelqu'un sait ce qui ne va pas?

3
demandé sur coder 2012-01-13 20:36:12

8 réponses

vous devez toujours fermer la base de données sqlite après l'avoir utilisé ... ajoutez donc cette ligne sqlite3_close(DB); juste après sqlite3_finalize(statement);

mettre à Jour

Vous êtes de retour OUI à l'une de vos boucles while -

        while (sqlite3_step(statement) == SQLITE_ROW)
        {
            return YES;
            break;
        }

donc ici vous êtes ni finalisation ni fermeture de la base de données.. vous devez fermer si chaque fois que vous l'ouvrez

11
répondu Saurabh 2012-01-13 17:47:48

votre base de données est ouverte fermer en utilisant sqlite3_close (db) si vous ne fermez pas alors le processus qui a accédé à votre base de données sera en cours d'exécution arrière-plan ce qui causera une erreur dans la base de données.

si vous voulez supprimer l'erreur database is locked puis suivre ces étapes 1.copiez votre fichier de base de données à un autre endroit. 2.puis remplacer la base de données avec la base de données copiée 3.cela déréférencera tous les processus qui accédaient à votre fichier de base de données

4
répondu vinayak jadi 2012-12-04 07:44:28

mais notez que si vous accédez à la même base de données SQLite à partir de plusieurs threads, sans une sorte de synchronisation séparée (une façon de savoir que vous n'aurez jamais d'accès quasi simultanés à partir de plusieurs threads) alors vous êtes susceptible d'obtenir des erreurs "database locked" même si vous fermez tout correctement sur chaque accès.

SQLite ne fournit aucune sorte de" lock wait " mécanisme.

vos options de base sont:

  1. faites tous les accès à partir d'un seul fil.
  2. utilisez un protocole de verrouillage séparé autour de tous les accès.
  3. si vous obtenez une erreur" database locked " attendez une courte période de temps et réessayez.
3
répondu Hot Licks 2012-01-13 18:00:59

Votre base de données est ouverte. Fermez-le en utilisant sqlite3_close(db) .

si vous ne fermez pas, alors le processus qui accède à votre base de données lancera background qui causera une erreur de verrouillage de la base de données.

3
répondu prashant wadi 2013-02-27 07:44:21

Si vous avez essayé sqlite3_close(DB) c'est probablement parce que vos méthodes tentent d'accéder à la même base de données en même temps. Essayez de placer cette ligne de code

sqlite3_busy_timeout(DB, 500);

quelque part entre l'appel"sqlite3_open "et le message d'erreur"sqlite3_prepare_v2".

la connexion à la base de données dans cette méthode essayera alors d'écrire/lire en 500 millisecondes avant qu'elle ne lâche, ce qui est généralement assez de temps pour échapper au verrouillage.

2
répondu turingtested 2015-12-15 05:45:43

pour une chose, vous ne fermez pas la connexion de base de données avec sqlite3_close () avant d'ouvrir une nouvelle connexion

0
répondu meggar 2012-01-13 17:40:23

je viens de passer une heure avec le même problème. Le problème pour moi a surgi quand j'ai involontairement tué un processus en fermant l'interpréteur de commandes (quand le script exécutait une boucle et une minuterie de type while), alors qu'un fichier DB JOURNAL temp était encore ouvert. Windows ne tue pas le processus même si vous l'avez tué en Python, peu importe si vous avez utilisé db.fermez () ou finalisez dans le script; si vous quittez toutes les applications Python, il y en aura encore une dans le Gestionnaire des tâches.

donc vous aurez besoin de mettre fin à tous les processus Python dans Windows Task Manager, de les redémarrer, et ça devrait aller( si qui est en fait la cause du problème).

0
répondu user3439187 2014-04-11 04:16:04

j'ai eu le même problème il y a un moment. J'ai essayé de copier le fichier de base de données lui-même, l'ai renommé à un nom de fichier différent, puis vérifié - il a fonctionné!

j'utilise SQLite3.

j'espère que cela fonctionnera aussi pour vous!

-2
répondu Pinkoy Montano 2015-06-23 09:06:49