Debug a locked sqlite3 database

I am writing an iOS application that uses sqlite3 wrapped by fmdatabase. I encounter a problem that at some point my program gets stuck inside the FMDatabase libraries, in particular, a function that calls sqlite3_step and detects that the database is busy, and then repeats over and over again.

I am looking for general debugging tools and tips, as it will be too much to give my whole installation here. Some things that could have consequences, I opened a database descriptor for a database that already has a descriptor in another thread. sqlite3_threadsafe () returns 2, so I know that it is enabled. I also tested this new connection by making a very simple select and update statement. When I run my program and when it tries to start updating the database, I am stuck.

The update statement that my program does is not to blame, because this request is executed normally when I DO NOT open two connections. However, I do not see where I can be mistaken ...

Any help or advice on where I might be wrong would be greatly appreciated.

+4
source share
1 answer

SQLite locks the entire database during a write operation (i.e. when a record occurs in any table, no other record in any table anywhere can happen at the same time). Some databases provide simultaneous writes through table-level locks, or sometimes row-level locks. To compare this with the implementation of SQLite, table-level locking basically means that when you write data to a given table, no other thread can write to any record in this table at the same time (however, writes to other tables can occur simultaneously, in some cases). Similarly, row-level locks take it even more and only allow necessary rows to be locked, which allows simultaneous writing to the same table from multiple threads. The idea here is to minimize the amount of data that needs to be locked for a write operation, which effectively increases the number of simultaneous records available in the database, and depending on your implementation / how you use your database, this may significantly increase throughput.

Now back to your question ...

The fact that SQLite is thread safe does not mean that multiple threads can write to it at the same time - it means that it has a way to handle access from multiple threads - i.e. (a) allow timeouts / retries and (b), to return a useful error (SQLITE: Busy) when the lock is currently stored in the database. That is, threadsafe means nothing more than "Multiple threads can access this data in such a way as not to damage the data due to simultaneous access."

Basically, somewhere in the code, one thread tries to perform its update before another thread releases its lock in the database. This is a common hurdle with SQLite, because the authors / documentation will tell you that SQLite can handle concurrency like a champion. The reality is that SQLite believes that โ€œw391 supportโ€ is an attempt to be very fast, so that database locks are only retained for a very short time, and therefore database locks are released before timeouts are removed. In many cases, this works great and never bothers you. However, the presence of very short circuits is not the same as actually allowing simultaneous recording from several streams.

Think of it as how iOS does multitasking (at least with iOS 5 when I write this) - indeed, this is what other applications pause and return to. This means that (a) the battery life is much better due to lower CPU usage and (b) you do not need to start the application from scratch every time you start it. That's great, but the actual word "multitasking" used in iOS doesn't technically mean the same thing as "multitasking" in other environments (even Mac OS X).

SQLite is similar. Do they have concurrency support? Well, it seems, but the way they define the word "concurrency" does not correspond to the fact that the rest of the database world defines "concurrency".

No one is mistaken, but in such cases, it adds to the confusion of implementation.

+21
source

All Articles