In my database handler class (extends SQLiteOpenHelper) I have the onCreate()
Method:
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_TABLE_TASKS);
db.execSQL(CREATE_TABLE_CONTACTS);
}
Sometimes (very rarely, but still) this leads to a crash because apparently the first table already exists. Obviously I can (and did) add IF NOT EXISTS
to the statement to fix this, but what I want to know is what are the circumstances where onCreate()
would be run if the table already exists. That is ordinarily not supposed to happen, so I've probably messed something up, but I can't figure out what.
I want to know is what are the circumstances where
onCreate()
would be run if the table already exists
Race condition: More than one thread trying to get a hold of the database via getReadableDatabase()
or getWritableDatabase()
.
Specifically if the threads are interleaved between getVersion()
and setVersion()
in the code:
242 final int version = db.getVersion();
243 if (version != mNewVersion) {
...
251 if (version == 0) {
252 onCreate(db);
253 } else {
254 if (version > mNewVersion) {
255 onDowngrade(db, version, mNewVersion);
256 } else {
257 onUpgrade(db, version, mNewVersion);
258 }
259 }
260 db.setVersion(mNewVersion);
There's a non-trivial amount of processing and some disk I/O involved so it's not hard for two threads to end up in this race.
Possible solutions:
Synchronization: Use Java synchronization primitives to prevent the other thread from attempting to create the database at the same time.
Singleton with synchronization. Ensure there's only one database helper.
Access the database only in a single thread.