DataBaseHelper, Singleton or not? - android

There have been a few questions on this topic but none giving firm reasons for why there should or shouldn't be a single or multiple instances of the databaseHelper.
When is it a good idea to have multiple instances of DatabaseHelper and when is it not. Is less complexity (if that is actually the case ) a good enough reason to have just a single instance ?

Your DatabaseHelper should be a singleton for sure. Each helper maintains the single connection to the database. If you have multiple helpers with connections to the same database, then concurrency issues will result. Sqlite does it's own locking underneath the single connection to ensure proper concurrent access to the database so using that single connection (and therefore that single helper) for all of your database operations is recommended and required.

Use one DatabaseHelper for each database in the application. SQLite takes care of file locking for you (many reads, only one write) and Android using Java locking in SQLiteDatabase. However, you can still get have a concurrency failure (simulataneous connections writing at once). It's the multiple connnections part that you want to avoid and that is what is managed by one instance of the DatabaseHelper.

Related

SQLiteOpenHelper single connection vs multiple connections

I am very much confused regarding access to SQLiteDatabase. Either it should be one connection or multiple connections to have access from multiple threads. I have read many articles including following two.
https://stackoverflow.com/a/3689883/3027124
http://touchlabblog.tumblr.com/post/24474398246/android-sqlite-locking
Both of these recommends to have single connection. Even my own answer to same question was accepted by OP. I used the Singleton approach to access SQLiteopenHelper class.
https://stackoverflow.com/a/35358702/3027124
But I am still confused after reading documentation of enableWriteAheadLogging which states
This method enables parallel execution of queries from multiple
threads on the same database. It does this by opening multiple
connections to the database and using a different database connection
for each query. The database journal mode is also changed to enable
writes to proceed concurrently with reads.
Now this is the confusing part. If I want to access database from simultaneous multiple threads, I have Singleton access to SQLiteOpenHelper which in my understanding means the serial execution of insertions while Simultaneous reads can be done with no-errors. But above documentation says, in order to have Simultaneous access, enableWriteAheadLogging should be called which in returns create multiple connections. What is this going on?? What does it mean if I do insertions by calling getWritableDatabase() using Singleton SQLiteOpenHelper from multiple threads? Will the calls be serial? Should enableWriteAheadLogging be called?
Please clarify.
I would use the singleton instance whether I'm using enableWriteAheadLogging or not when dealing with threading which is the case in most apps unless it's a very trivial app like a sample.
Using a singleton instance is ensuring Thread Safety: The singleton instance ensures that synchronization works across that instance, that means when you have a read and write methods calling the database at the same time from different threads, one of them should wait for the other as the database gets locked while writing to it.
It's really clear that this is the case as written in the documentation and quoted below
it is not
possible for reads and writes to occur on the database at the same
time. Before modifying the database, the writer implicitly acquires an
exclusive lock on the database which prevents readers from accessing
the database until the write is completed.
enableWriteAheadLogging is actually altering the above behavior as the above statement is only true When write-ahead logging is not enabled (the default).
So what happens when you enable write-ahead logging through enableWriteAheadLogging?
It's actually changing the default behavior enabling actual parralism as it changes the underlying database journal file to enable doing a write and a read at the same time, but to do that it needs more memory than usual. Read the documentation quote below to know more!
In contrast, when write-ahead logging is enabled (by calling this
method), write operations occur in a separate log file which allows
reads to proceed concurrently. While a write is in progress, readers
on other threads will perceive the state of the database as it was
before the write began. When the write completes, readers on other
threads will then perceive the new state of the database.
It is a good idea to enable write-ahead logging whenever a database
will be concurrently accessed and modified by multiple threads at the
same time. However, write-ahead logging uses significantly more memory
than ordinary journaling because there are multiple connections to the
same database. So if a database will only be used by a single thread,
or if optimizing concurrency is not very important, then write-ahead
logging should be disabled.

database since different activities in android

I'm trying to access since different activities to an unique database, however when I work with databases I have to create a different database instance since every activity and this produce an unwanted result, how can i manage an unique database since different activities?
however when I work with databases I have to create a diferent
database instance since every activity and this produce an unwanted
result, how can i manage an unique database since diferents
activities?
So did you think about Singleton? I think your problem is directly designated for an usage of Singleton design pattern. An usage has only benefits(always only one instance, not wasting of memory, clean and human-readable code etc.).
Let's write some code:
private static SQLiteOpenHelper instance;
public static SQLiteOpenHelper getInstance(Context c) {
if (instance == null) {
instance = new SQLiteOpenHelperImplementation(c);
}
return instance;
}
I have only good experiences with Singleton.
Notes:
To improve your work with database i have a few suggestions for you:
If you have more than one table, i suggest you to create "operation"
classes which will wrap CRUD operations and specific methods for each
table.
To improve performance, security and integrity of db always use
TRANSACTIONS. It's very useful and efficient practise
In concurrent programming, always use synchronized blocks and methods to avoid problems related to access to database and making changes
Always when work is done, release your cursors and close database

Android SQLite : Lock + access from multiple threads

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.

Managing SQLite Connections in Android

I have a (hopefully) quick question regarding handling SQLite database connections in Android. I have an app that is composed, naturally, of several activities. I have no trouble creating/updating/querying the database, as I've created a single, dedicated class to handle that work via SQLiteOpenHelper, etc.
My question is this: since these activities all share this same database, is this usually implemented as a single, static member, or should each activity own its own connection? My concern of course is the cost of re-connecting to the database in each activity.
Or, put another way, is there any reason not to just store a singleton instance?
I'm also wondering if there's something going on behind the scenes similar to .NET's connection pooling to reduce the cost of opening connections.
Thanks in advance!
Connection opening in SQLite is about 0.2ms.
The best practice tells us to open and close the connection each time we need one.
Just use SQLiteOpenHelper.getReadableDatabase() and SQLiteOpenHelper.getWriteableDatabase() - Android will manage and cache the connection so you don't need to.
In fact, refer to the official Google Using Databases documentation:
To write to and read from the
database, call getWritableDatabase()
and getReadableDatabase(),
respectively. These both return a
SQLiteDatabase

Closing an SQLite database on one thread breaks the database opened on another thread

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.

Categories

Resources