简体   繁体   中英

Synchronize sqlite database in objective-C

I have a view in which I am inserting data in a background thread to sqlite database coming from server. Now when user taps and navigate to another view in which I have to read the contents from this database, but I am not able to fetch the contents as the database is already open in background thread of last view and it gives error "database is locked".

NOTE: both the operations are in different Tables ie I am writing in different table and reading from other table.

Does sqlite support multi threading, If yes then how can I remove the lock from database?

SQLite does support multi-threading, but it does not support simultaneous access to the database from multiple threads.

If you are accessing SQLite from multiple threads in Objective-C you should use some kind of locking mechanism to coordinate access to the database handle. One option is the @synchronized keyword.

As for reading from the database at the same time that inserts are happening on a different thread, you'll need to get creative.

One option is to put the two tables into two different databases and create two different connections to them.

Further reading on the nature of using SQLite in a multi-threaded environment:

http://www.sqlite.org/threadsafe.html

http://www.sqlite.org/faq.html#q6

SQLite supports multithreading. You can share your connection handle/object between threads, they'll sync their access nicely.

EDIT: pass the sqlite3 object (the one that sqlite3_open() returns as the second parameter) to the thread instead of reopening the database in the thread. Something like this:

sqlite3 *MyDatabase; //Initialized somewhere
NSArray *DataForThread = [NSArray arrayWithObjects:
    request,
    [NSValue valueWithPointer: MyDatabase],
    nil];

[self performSelectorInBackground:@selector(processResponseInBackground:)        withObject:DataForThread];

Inside the thread, recover the SQLite3 object like this:

sqlite3 *MyDatabase = [[ThreadData objectAtIndex:1] pointerValue];

Sqlite supports multi-threading in the sense of "writing so fast to avoid concurrency problems". The reality is that there shouldn't be lock troubles in case of read only queries but if you want to write too... you could meet the SQLITE_BUSY error. You can avoid it in several ways:

  • either doing all queries into the same thread (but if you could do it...no questions on stackoverflow :-) )

  • or, as mentioned above, split database tables into two or more files (grouping together tables with less concurrency accesses or with read only accesses) and creating for each file a different db connection

  • or, as mentioned above, using a thread synchronizing approach on each method (or block of code) that does the query (to be sure that db will be locked when you start the transaction use "BEGIN IMMEDIATE TRANSACTION")

  • or, handle the sqlite:busy error with the 2 callbacks provided by the c api, "sqlite_busy_handler" and "sqlite_busy_timeout"

  • or, after receiving lock errors waiting for 1-2 seconds and retry (better approach the point above i think)

I prefer to reduce concurrency splitting db and then if needed synchronizing threads accesses to query code. It's just your choice...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM