-
Notifications
You must be signed in to change notification settings - Fork 298
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
'Database is busy' #34
Comments
It might be relevant that I'm using multiple pull CBLReplications to pull data from the same remote database, to the same CBLDatabase instance, with different query_params for the sync_gateway/channels filter. |
I think you need to create multiple CBLManager instances and create pull replications from each of those instances with the different query_params. |
That should never happen — FMDB doesn't support multithreaded access. But the warning for this is different, reading "The FMDatabase %@ is currently in use." It will also trigger an assertion failure in a debug build. The error you're getting looks like the database file is being used by multiple threads (with one FMDB connection per thread) and one of the connections is leaving the database locked too long. This is possible, especially since looking at the retry logic in FMDB it'll give up after 200ms. Try this: edit the following line in CBLDatabase+Internal.m: Let me know if that fixes the problem, and if you see any unexpectedly long pauses. |
I changed the value to zero. In lieu of having the warning messages, I know have FMDB lock the entire app by sleeping the main thread indefinitely. Here's a backtrace after pausing in lldb when the app locks up.
|
Could you get a dump of all threads? (I'm not sure what the LLDB command for that is...) There's probably some other thread that's locked up inside an FMDB call. Or if not it's really bad news, because that means something previously managed to return while leaving a transaction open, which should be impossible. |
There doesn't seem to be anything else happening on other threads. Here's the full bt.
|
You've got a CBL_Server running on thread 6, so there must have been some background activity. Either you've started the HTTP listener, or you've called |
I don't believe I've done either :-)
|
Oh right, sorry — I did that last month to optimize CBLLiveQuery. OK, so that narrows down what could be running on the other FMDB connection. Still can't figure out what could be wrong, though. |
Could you retry with the latest commit? It adds some assertions and warnings about transactions. I think it was possible for the transaction level to get confused, but only in cases where sqlite itself fails to commit or back out a transaction, and I don't think either is likely to have happened. |
Ok, I tried again and I am getting the same messages as before. |
/scratching my head/ Could you please turn on This looks like a nasty problem, and I'm glad you've run into it before I moved replication to the background thread; hopefully it'll be easier to figure out in this more limited scenario. |
Sure. I used the code below to enable logging and sent the logs to you by email.
|
You can enable logs by going into the Arguments tab of the Run item of the scheme editor and adding items
Then you can check and uncheck them. Also, Cmd-Opt-R will open that editor before running the target, making it super easy to update the arguments. |
Got the emailed logs, thanks. That's actually less detail than I wanted — I forgot to have you enable I think I know what's going on, though. This has to do with SQLite's "deferred transaction" feature. I'll have to go reread the docs, but IIRC, the thread may legitimately have to back out of its transaction and retry, if another thread is already holding a lock it needs. I ran into this once before; but I hadn't noticed that the "savepoint" mechanism TouchDB and CBL use is based on deferred transactions. |
Good to know, thanks. It doesn't seem to have any devastating effect on data as far as I can tell. |
Whew — I just pushed a big commit that should cause CBL to handle db-busy errors correctly by backing off and retrying. There are a lot of code changes, but it passes all the unit tests. I don't have any code that reproduces your bug, though. Could you give this a try with your app? If the SQLITE_BUSY error happens internally, you should see a log message like "Db busy, retrying transaction (#1)...". This will show up if any logging is enabled (-Log YES), you don't have to turn on CBLDatabase logging. There might be more than one of these if the other thread is taking a long time; but at some point it should succeed. |
On 'Database busy' I now see '05:46:53.307| CBLDatabase[<0x88accf0>user-e1b1c275376b67ba7ce277e6560207cc]: Db busy, retrying transaction (#1)...' like you said, but I no longer have any view update failure messages! |
W00t! High-five! |
It seems the underlying FMDB database is sometimes accessed from multiple threads at the 'same time'. My app isn't using any concurrency, dispatch queues or threads, yet I'm running into these issues when using live queries during a pull from a remote sync gateway. Not sure if it's relevant, but most of the documents being pulled contain attachments.
The log below show two different threads are trying to use the FMDatabase.
The text was updated successfully, but these errors were encountered: