2011-10-28 16 views
27

Viene visualizzato l'errore seguente. Quindi, come posso sbloccare il mio database?Database Android bloccato

10-28 08:43:26.510: ERROR/AndroidRuntime(881): FATAL EXCEPTION: Thread-11 
10-28 08:43:26.510: ERROR/AndroidRuntime(881): android.database.sqlite.SQLiteDatabaseLockedException: database is locked 
10-28 08:43:26.510: ERROR/AndroidRuntime(881):  at android.database.sqlite.SQLiteDatabase.dbopen(Native Method) 
10-28 08:43:26.510: ERROR/AndroidRuntime(881):  at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:983) 
10-28 08:43:26.510: ERROR/AndroidRuntime(881):  at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:956) 
10-28 08:43:26.510: ERROR/AndroidRuntime(881):  at android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:1021) 
10-28 08:43:26.510: ERROR/AndroidRuntime(881):  at android.app.ContextImpl.openOrCreateDatabase(ContextImpl.java:742) 
10-28 08:43:26.510: ERROR/AndroidRuntime(881):  at android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java:221) 
10-28 08:43:26.510: ERROR/AndroidRuntime(881):  at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:149) 
10-28 08:43:26.510: ERROR/AndroidRuntime(881):  at com.aa.me.vianet.dbAdapter.DbAdapter.open(DbAdapter.java:25) 
10-28 08:43:26.510: ERROR/AndroidRuntime(881):  at com.aa.me.vianet.services.NotificationManagerThread.run(NotificationManagerThread.java:49) 
+0

1. Assicurarsi di utilizzare un solo SQLiteOpenHelper sullo stesso file. 2.Assicurarsi che solo un thread alla volta stia utilizzando SQLiteDatabase. – Jens

risposta

32

Penso che tu abbia dimenticato di chiudere il database o che un altro thread stia scrivendo nel database quando stai provando a scrivere su di esso. SQLite blocca il database quando lo scrive per evitare la corruzione se un'altra entità tenta di scrivere nello stesso database allo stesso tempo. Android, mostrerà solo un errore nel registro gatto, e la query da Lei forniti saranno solo dimenticato ...

Quindi, mi raccomando:

  • Hai solo accedere al database da un SQLOpenHelper
  • È assicurati di aver chiuso tutte le istanze degli helper del database una volta terminato con loro
  • Assicurati di terminare sempre le transazioni con endTransaction() anche se non le hai impostate correttamente (cioè se vuoi ripristinarle), nel caso tu utilizzare le transazioni
  • Si potrebbe provare a utilizzare OrmLite, non l'ho usato, ma ne ho ascoltati altri entusiasti.
+5

Ho scritto la porta originale di OrmLite su Android. La tua prima raccomandazione, usa solo un aiutante, è un buon consiglio. Il tuo secondo contraddice il tuo primo. "chiudere tutte le istanze degli helper del database" implica più di 1. UTILIZZARE UNO SOLO, SEMPRE !!! Inoltre, non è necessario chiudere le connessioni di supporto. Per favore vedi la mia risposta. Originariamente ho scritto un codice di conteggio di riferimento complesso per OrmLite per aiutare a mantenere vivo un helper e chiuderlo quando hai finito, ma come risulta, le "connessioni" Sqlite sono solo maniglie di file. Il sistema li chiuderà per te quando scarica il processo. –

+0

Hey Kevin, vuol dire che non devi mai chiudere il gestore del tuo database? –

+2

Sì. So che suona male. Il gestore è solo un handle di file. Si chiuderà quando il processo muore. SQLite non si corromperà da solo. Come per mostrare solo un errore in logcat, è vero per "insert" ma non per altri metodi. Questo è il motivo per cui dovresti sempre chiamare "insertOrThrow". –

7

La ragione per questo sta accadendo è perché si può avere solo una connessione al database aperto alla volta (questo è quello di evitare condizioni di gara durante la modifica del database). Sto indovinando il tuo collegamento più volte al tuo database da thread diversi? Il modo più semplice per aggirare questo è semplicemente creare un frontend ContentProvider per il tuo database. Questo sarà in grado di gestire le query da più thread.

Per ulteriori informazioni, controllare questo blogpost.

+0

il collegamento del blogpost è interrotto, il nuovo collegamento è http://www.touchlab.co/blog/android-sqlite-locking/ – pengwang

+0

interrotto ancora una volta. – christophercotton

+0

@christophercotton Sembra che stia funzionando di nuovo bene per me. –

11

Utilizzare un'unica connessione per l'intera app. Vedi qui:

http://touchlabblog.tumblr.com/post/24474750219/single-sqlite-connection

+0

Puoi correggere questo link? Come gestisci l'accesso multithreaded con una singola connessione? – Michael

+0

@Michael Fixed link! –

+0

Ho usato questo metodo ma non funziona nel mio caso, per favore dai un'occhiata alla mia domanda [link is here ...] (http://stackoverflow.com/questions/13859840/application-crashes-on-installation -with-error-sqlite3-exec-failed-to-set-sync) – MobileEvangelist

0

ho avuto un errore simile. Il mio problema era che accidentalmente davo ai database delle due classi helper lo stesso nome, quindi hanno finito per accedere contemporaneamente allo stesso database. Quindi assicurati di non accedere a un singolo database con più classi helper.

2

Ho avuto lo stesso problema, provare a utilizzare questa

db.beginTransactionNonExclusive(); 
    try { 
     //do some insertions or whatever you need 
     db.setTransactionSuccessful(); 
    } finally { 
     db.endTransaction(); 
    } 

ho provato con db.beginTransaction ma bloccato la bd

0

Ho avuto lo stesso problema, come stavo cercando di accedere alla mia base di dati tramite un ContentResolver mentre avevo già una connessione diretta SQLiteDatabase aperta (necessaria per le transazioni).

Ho risolto il problema modificando l'ordine del mio codice in modo che la roba ContentResolver venga eseguita prima che venga aperta la mia connessione diretta SQLiteDatabase.

Ho rimosso anche del codice in modo da non chiudere più la mia diretta SQLiteDatabase.

Vale la pena leggere this answer in quanto fornisce molte altre utili indicazioni.

Problemi correlati