In my scenario it has Sync_Class that syncs, with AsyncTasks in background , from my app to my server.
Every time that my app does one action that need to change data from my SQLite, as first step my app updates my local database as second step throws a AsyncTask in background to start the sync with my server. In the 80% of cases my app works great but the other 20% of cases throws a IllegalStateException because the app try to re-open the connection or open a closed connection, when I have a method to open database in 6 lines more above. In this cases I think the problem is multiple simultaneous acceses in database, I'm right?
In the differents posts that I can read, the people talk about de SQLite can't execute a simultaneous connections and it serialized connections because file structures not permit... The final question is, If we do multiples asyncTasks with sqlite connections to do inserts, updates and deletes, to harness the full power of the processor with parallel programming, we have any tools for do this? Or it's a non-viable option and we need to do a serialized connections?
If you have any solutions or any ideas for my problem, help me!! Thanks in advance!!
More info:
My BDDclass have a method for open database. When I need to execute query, rawquery, etc... in a simple function or void I call my database class, opens database, executes the query or multiple queries and at the end we close the database. When I know that i have a large process with a multiples functions with querys in this case I create BDDclass and opens bdd at start and at the end closes the database of this process.
I say this because I can see some posts that people recommend use the SQLiteHelper because this helps to administrate multiple simultaneous connections in SQLite, but others posts says that have the same problem that I have... Then it's must to use SQLiteHelper? Or not?
If you need more information or something let me know.
Finally I solved the problem!! The problem is that I try to control the acceses to the database, opening and closing the databases when I need read or write in the databases with parallel programming (background asyncTasks).
Must remember that I don't use SQLiteHelper and I solved the problem calling my database class one time per activity, this mean open my database one time and close this when my app is pause and reconect with BDD when my app come in first plane other time then connects with my database.
In resume, never close your database and you can use a parallel programming with multiple accesses in SQLite. Greetings!!
Related
I am working on a chat application and in chat we are getting lots of update from server. And we are also saving the updates into the local SQLite database file.
Can someone suggest me, after every single insertion/update, should we close the database or we should close the database when it is actually needed ?
Closing the connection throws away the page cache, and requires that the schema version is checked and the entire schema is re-parsed the next time it is opened.
In most apps, there are not enough database accesses so that the overhead of continually re-opening the database would actually become noticeable. But this is no reason to add useless code to your app.
Please note that the SQLiteDatabase object is reference counted. So if you are using a global open helper instance, you can keep the DB open with an extra getWritableDatabase() call, even when all your other code calls close().
You should close the connection after each query.
In .net (and in most other frameworks), SQLConnections are stored in the background anyway. It won´t hit your runtime.
Also: connection pooling is your friend.
I am planning on writing an application that saves a fair amount of data. Historically, I have simply written data directly to a server, and only used some simple key/value storage with shared preferences for local storage.
I am considering this time, instead, using SQLite to save the information at first, and sync the data to the server in the background later. This will benefit the user in a few ways: 1) can use the app offline 2) don't have to worry about data being saved right away, it happens when ever it can 3) more reliability.
My approach will be to get/set data from SQLite during UI usage, and use a background process to find new rows and put them on the server, flagging them as synced when it happens.
Does this sound reasonable?
You can use SQLIte for your scenario. But, while implementing, you can follow any one of this approach.
Approach #1: Use an Abstract Factory to Instantiate the SQLiteOpenHelper.
Approach #2: Wrap the SQLiteDatabase in a ContentProvider
Refer to this link for how to implement these 2 approaches. http://www.androiddesignpatterns.com/2012/05/correctly-managing-your-sqlite-database.html
Key points to be noted while using SQLite
Sqlite takes care of the file level locking.
Many threads can read,one can write. The locks prevent more than one
writing.
Android implements some java locking in SQLiteDatabase to help keep
things straight.
If we handle the database incorrectly from many threads and mess up the code, your
database will not be corrupted. Only few updates will be lost.
How "Multiple Threads - DB access" can be used for your scenario
The SqliteOpenHelper object holds on to one database connection.
If you try to write to the database from actual distinct connections (multiple threads) 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 recommended to write using single thread and read from multiple threads if necessary for faster access.
Does this sound reasonable?
Yes. Note that the synchronization process can get tricky (e.g., what happens if the server hiccups halfway through?), but that has mostly to do with synchronization and little to do with SQLite.
We implemented a solution that used a SQLite db on the device to sync data via a web service to the master database. We did this for a couple reasons: offline, poor connection, manual sync.
For our solution we had a flag on the table that determined if the data was pushed to the web service. Our web service also provided data back to our application to let us know if the data was received and processed correctly. This allowed us to clean up the data on the device, send notifications if there were failures, and resubmit the data if there were previous failures.
You can use push notifications as well if you have fixed the issues on the backend and have the device resend the data to the web service. This worked really well for us.
My application has :
Activity A that reads from sqlite database
Service with notification that writes to the database
on clicking Notification, Activity A opens up
the reading by ActivityA is very small task(in reference to time taken to read)
but the writing by the service to the database is very long(it sometimes takes 5-10min)
now when the service is running and i click on the notification, ActivityA that has to read from the database cannot perform its reading as there is already a service writing to that database.
so activityA has to wait (for 5-10min) to read from database.
on researching further i came across this
http://developer.android.com/reference/android/database/sqlite/SQLiteDatabase.html#beginTransactionNonExclusive()
when i try to implement this in my method inside sqliteopenhelper class i get error as my application uses min api 10. so how do i get this method working for api 10 or is there anyother way to have parallel database access
?
is there anyother way to have parallel database access ?
I think there is no special way how to achieve it. You should use classic Java synchronization for synchronized access to your database.
Most important thing is that you have to make sure you have only one connection to database (you can't write/read from two different connections in the same time). And try to think about an usage of Singleton. In this case (and also in others) it's very efficient and clean solution and you can avoid many problems with access to db.
You mentioned that your task can last 5-10 min.
In similar cases every user should know that you are performing some calculations in the background e.q. show some progressDialog, progressBar or simply start animation of image.
If you are showing some data for example in List this is good reason to use lazy loading.
Have look also at these articles:
Android Sqlite Locking
Using Singleton design pattern for SQLiteDatabase
I am trying to understand the possible ways to work with SQLite when there can be multiple threads work on DB.
Based on various responses in stackoverflow and other sites, it appears that there will be locking issue when same sqlitehelper instance is used from multiple threads. In a typical java application, I would expect instance to mean single object of type sqlite helper to be used by different threads of application.In such cases, the locks ,I guess, are a matter of correctly using the synchronized blocks. [Correct me here as I am not comfortable with this way of looking at sqliethelper instance here]
My concern is with sharing same data base : when one instantiate sqlite helper in different threads [ie each thread has its own object instance] but working on same Database [this I guess is more inline with having same db instance].
In such cases I'm getting frequent database lock errors. This occurs even when the threads are working on different tables of database.
In my application database can be updated by user interaction through application or by getting data through server [periodic synchronization]. And some time when synchronization process and user activity overlaps, I get the lock issues. As this pattern of data processing seems to be common in application synchronizing with server, would like to know how do lock issue due the concurrency is to be handled.
I would like to understand this since if this is bound to happen always then probably need to make only one handler over database and implement queue over that to avoid lock. But that will mean the complete application needs to be aware that the database may not get updated immediately and they need to implement listener to know when the data is actually updated in database.
thanks
pradeep
As far as I know sqlite is intended for single process usage. No matter what you will always need to access the database from one thread at a time. You can do selects from multiple clients but can only write from one at a time. And other readers and writers will ahve to lock in the mean time.
As a side note - database access can hardly ever be considered instantaneous.
We all learn that resources, such as database connections, should be acquired late and released early.
Yet applying this principle to SQLite database connections on Android have caused me some headache.
I have an app that download updates from a backend server in a service working in the background, writing updates to the database at a regular basis. The problem I experience arise when the following sequence occurs:
Service opens a writable database connection
Some activity opens a readable database connection
Service closes its database connection concurrently with the activity reading data
Activity fails due to its database connection was closed
Both the service and the activity uses the same SQLiteOpenHelper class, though different instances, to open their connections. My initial assumption was that this should work just fine, but somehow it seems that the underlying connection is shared between the two database instances.
To work around the problem I ended up not closing the database objects, only closing any opened cursors. This seems to work, though I'm not sure that I'm not leaking memory here.
Is there something obvious I am missing here?
Is there something obvious I am missing here?
I'd say no. Looking at the source code to SQLiteOpenHelper, I can't see how two instances could be sharing a SQLiteDatabase object.
Some diagnostic suggestions:
Dump the toString() value of each SQLiteDatabase, which should give you a Java instance ID. If they are the same, that is where your problem lies, and you will need to work your way upstream to figure out how the heck this is happening (e.g., you really are using the same instance of the SQLiteOpenHelper).
With your database in a stable state (i.e., no need to create or upgrade), flip one of your two database spots to use SQLiteDatabase directly, rather than via SQLiteOpenHelper, and see if that changes matters.