Android Database Locked
Asked Answered
P

8

47

I am getting following error. So how do I unlock my database?

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)
Praxiteles answered 28/10, 2011 at 13:50 Comment(1)
1. Ensure that you're only using a single SQLiteOpenHelper on the same file. 2. Ensure that only one thread at a time is using your SQLiteDatabase.Lessor
P
50

I think you have forgotten to close the database, or another thread is writing to the database when you are trying to write to it. SQLite locks the database when it is writing to it to avoid corruption if another entity tries to write to the same database at the same time. Android, will only show a error in log cat, and the query you supplied will be just forgotten...

So, I recommend:

  • You only access the database from one SQLOpenHelper
  • You make sure you close all instances of database helpers once you have finished with them
  • You make sure you always end transactions with endTransaction() also if you do not set them successful (i.e. if you want to roll 'em back), in case you use transactions
  • You could try using OrmLite, I've not used it, but I've heard others here rave about it.
Passus answered 28/10, 2011 at 14:12 Comment(6)
I wrote the original port of OrmLite to Android. Your first recommendation, use only one helper, is good advice. Your second contradicts your first. "close all instances of database helpers" implies more than 1. ONLY USE ONE, ALWAYS!!! Also, you don't need to close your helper connections. Please see my answer. Originally I wrote complex reference counting code for OrmLite to help keep one helper live, and close it when you were done, but as it turns out, Sqlite "connections" are just file handles. The system will close them for you when it dumps the process.Transliterate
Hey Kevin, does this mean you never really have to close your database handler?Passus
Yes. I know that sounds bad. The handler is just a file handle. It will close when the process dies. SQLite won't corrupt itself. As for only showing an error in logcat, that is true for "insert" but not other methods. That is why you should always call "insertOrThrow".Transliterate
Are there any good tutorials on this, I've never come across a comprehensive tutorial on SQLite in Android :-( Thanks :DPassus
Yes, see my answer here: #2493831 It links to various examples of best practices.Transliterate
If I want to take a backup of my database - and backup locks the database supposedly - then, am I forced to actually close my helper, or can it still be open, me just not writing to it during the time of the backup?Cobalt
T
15

Use a single connection throughout your whole app. See here:

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

Transliterate answered 4/5, 2012 at 15:59 Comment(3)
Can you fix this link? How do you handle multithreaded access with a single connection?Hyohyoid
I used this method but doesn't working in my case please take a look at my question link is here...Robbinrobbins
You're using external APIs that are doing weird things. I would guess you need to adjust how you're calling their apis. Its unlikely that UrbanAirship is having that kind of crash regularly.Transliterate
D
8

The reason this is happening is because you can only have one connection to the database open at a time (this is to prevent race conditions when modifying the database). I'm guessing your connecting multiple times to your database from different threads? The easiest way to get around this is to just create a ContentProvider frontend for your database. This will be able to handle queries from multiple threads.

For more information, checkout this blogpost.

Damage answered 28/10, 2011 at 14:6 Comment(3)
the link of blogpost is break ,the new link is touchlab.co/blog/android-sqlite-lockingTransducer
It wasn't, and neither was the "new link" but now the blogpost seems to work, though the "new link" is still broken.Symphonist
i am using database in the multiprocess application. and only few users are facing this issue. Can you tell please what is the solution for this. database is locked (code 5): , while compiling: PRAGMA journal_modeCrape
P
7

I had the same problem, try using this

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

I tried with db.beginTransaction but it locked the bd

Pratt answered 10/6, 2015 at 17:11 Comment(0)
M
0

I had a similar error. My problem was that I accidentally gave the databases of the two helper classes the same name so they consequently ended up accessing the same database simultaneously. So ensure you aren't accessing a single database with multiple helper classes.

Milestone answered 7/3, 2015 at 8:33 Comment(0)
L
0

I had the same problem as I was trying to access my database via a ContentResolver whilst I already had a direct SQLiteDatabase connection open to it (required for transactions).

I solved it by changing the order of my code so the ContentResolver stuff is done before my direct SQLiteDatabase connection is opened.

I also removed some code so I no longer close my direct SQLiteDatabase.

It is worth reading this answer as it provides a lot of other helpful guidance.

Liszt answered 7/7, 2016 at 12:43 Comment(0)
S
0

In my case this error was due to common mistake. Initially, my SQLite database was populated by data received from JsonArray from MySQL. After I added additional column in SQLite database, the similar error happened. Simply, I forgot to add corresponding column in MySQL database.. :)

Sulphuric answered 30/1, 2020 at 8:24 Comment(0)
C
0

What we can do when we have been thrown an error like below.

android.database.sqlite.SQLiteDatabaseLockedException: database is locked

Database lock means the database is performing a task with some other threads and at the same time, other thread executing that time it occurs.

So the solution in my case is:

You have to check before executing query or doing transaction in database like this.

if(!sqLiteDatabase.isDbLockedByCurrentThread() && !sqLiteDatabase.isDbLockedByOtherThreads()) 
Churlish answered 31/3, 2021 at 6:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.