How can I avoid concurrency problems when using SQLite on Android?
Inserts, updates, deletes and reads are generally OK from multiple threads, but Brad's answer is not correct. You have to be careful with how you create your connections and use them. There are situations where your update calls will fail, even if your database doesn't get corrupted.
The basic answer.
The SqliteOpenHelper object holds on to one database connection. It appears to offer you a read and write connection, but it really doesn't. Call the read-only, and you'll get the write database connection regardless.
So, one helper instance, one db connection. Even if you use it from multiple threads, one connection at a time. The SqliteDatabase object uses java locks to keep access serialized. So, if 100 threads have one db instance, calls to the actual on-disk database are serialized.
So, one helper, one db connection, which is serialized in java code. One thread, 1000 threads, if you use one helper instance shared between them, all of your db access code is serial. And life is good (ish).
If you try to write to the database from actual distinct connections at the same time, one will fail. It will not wait till the first is done and then write. It will simply not write your change. Worse, if you don’t call the right version of insert/update on the SQLiteDatabase, you won’t get an exception. You’ll just get a message in your LogCat, and that will be it.
So, multiple threads? Use one helper. Period. If you KNOW only one thread will be writing, you MAY be able to use multiple connections, and your reads will be faster, but buyer beware. I haven't tested that much.
Here's a blog post with far more detail and an example app.
- Android Sqlite Locking (Updated link 6/18/2012)
- Android-Database-Locking-Collisions-Example by touchlab on GitHub
Gray and I are actually wrapping up an ORM tool, based off of his Ormlite, that works natively with Android database implementations, and follows the safe creation/calling structure I describe in the blog post. That should be out very soon. Take a look.
In the meantime, there is a follow up blog post:
- Single SQLite connection
Also checkout the fork by 2point0 of the previously mentioned locking example:
- Android-Database-Locking-Collisions-Example by 2point0 on GitHub
Concurrency issues in Android SQLite
It's not a great idea to be opening and closing the database regularly like this. Open it once on application startup, and reuse this connection throughout your app's lifetime. You don't even need to bother closing it. SQLite manages the concurrency by itself, so you don't need to worry about multiple threads either.
This will make all your "database is locked" errors go away, as well as make your code tidier and simpler.
Concurrency in SQLite database
You need to use a singleton object of DataBase
object. For this purpose you can use ContentProvider
. Which is a better option to achieve concurrency.
Here is link for tutorial on ContentProvider
http://www.vogella.com/articles/AndroidSQLite/article.html
You can refer the documentation also
http://developer.android.com/guide/topics/providers/content-providers.html
SQLite and concurrency
I don't think that SQLite would be a good solution for those requirements. SQLite is designed for local and lightweight use only, not to serve hundreds of requests.
I would recommend some other solution, for example MySQL
or PostgreSQL
, both can be scripted quite well. So, if I were you, I would put my efforts into the setup scriptings.
To avoid the flame war between SQLite believers and haters, let me draw draw your attention to the often referred SQLite When-To-Use document (I believe it is considered as a credible source). Here they state the following:
Situations Where A Client/Server RDBMS May Work Better
High Concurrency
SQLite supports an unlimited number of simultaneous readers, but it will only allow one writer at any instant in time. For many situations, this is not a problem. Writer queue up. Each application does its database work quickly and moves on, and no lock lasts for more than a few dozen milliseconds. But there are some applications that require more concurrency, and those applications may need to seek a different solution.
I think that in the referred question involves many writes and if the OP would go for SQLite, it would result a non-scalable solution.
Android sqlite concurrency without exceptions
So long as you're using the same SQLiteDatabase
object, the synchronisation is done for you.
So if you access the object via a singleton, there should be no problem. Though you may want to add some further logic if you want to implement a timeout, e.g. wait/notify or something similar.
Multithreading data writing in SQLite
After a long search i finally found a gret answer for my broblem, so anyone who want to creat e multithreading acess to db should read this first What are the best practices for SQLite on Android?
Android recycle view update sort list with concurrency issue
My solution is to hold updates in a buffer which can only fire after a time delay. Then putting the update objects into both a concurrent hashmap for easy object retrieval as well as a sortedlist for easy ui display
The api calls this method. I have another version that can run off the ui thread by simply detaching the adapter in sortedlist callbacks.
public void onResult(Object object) {
if ( !currentlyProcessing && System.currentTimeMillis() > (lastBatch + delay)) {
currentlyProcessing = true;
runOnUiThread(new Runnable() {
@Override
public void run() {
easyChatList.beginBatchedUpdates();
while (batchBuilder.size() > 0){
performBatch(batchBuilder.remove(0));
}
easyChatList.endBatchedUpdates();
lastBatch = System.currentTimeMillis();
currentlyProcessing = false;
}
});
}
}
The performbatch() handles a single update. If the object is new it puts it into a concurrent hashmap with its id as a key. Then adds it to the sortedlist. When an update occurs I pull the object from the hashmap, do the update and add it to the sortedlist. The sortedlist api then replaces the old object and updates the sort order.
edit:this does have a slight drag according to androids skipped frames warning. You can detach the adapter from the sortedlist and do updates on a worker thread but I'm not sure if that has any value as this is working alright for now.
Related Topics
Android: Install .Apk Programmatically
Get Real Path from Uri, Android Kitkat New Storage Access Framework
Sending Data Back to the Main Activity in Android
What Permission Do I Need to Access Internet from an Android Application
Basic Communication Between Two Fragments
Handler VS Asynctask VS Thread
Download Binary File from Okhttp
Volley Jsonobjectrequest Post Request Not Working
How to Do Something Like a Flowlayout in Android
How to Exit from the Application and Show the Home Screen
How to Correctly Save Instance State of Fragments in Back Stack
Exception 'Open Failed: Eacces (Permission Denied)' on Android
How to Draw a Path on a Map Using Kml File
"R Cannot Be Resolved to a Variable"
What's the Difference Between the Various Methods to Get an Android Context
Getting Exception "Illegalstateexception: Can Not Perform This Action After Onsaveinstancestate"
Firebase Data Desc Sorting in Android
Environment.Getexternalstoragedirectory() Deprecated in API Level 29 Java