Thank you for your valuable suggestion.

As you mentioned, the possibility of a concurrent transaction with
auto-commit transaction is already handled in our design using some flag
variables.

I would like to understand some points discussed in sqlite3 documentation
in detail.

1. Compile time configuration of sqlite3 library is serialized threading
mode. As per Sqlite3 documentation, this mode can be used reliably in
multithreaded application with no restriction.

2. Excerpt from https://sqlite.org/faq.html#q5 is as follows:

SQLite allows multiple processes to have the database file open at once,
and for multiple processes to read the database at once. When any process
wants to write, it must lock the entire database file for the duration of
its update. But that normally only takes a few milliseconds. Other
processes just wait on the writer to finish then continue about their
business.

3. *High Concurrency*

SQLite supports an unlimited number of simultaneous readers, but it will
only allow one writer at any instant in time. For many situations, this is
not a problem. Writers queue up. Each application does its database work
quickly and moves on, and no lock lasts for more than a few dozen
milliseconds. But there are some applications that require more
concurrency, and those applications may need to seek a different solution.

The above three items are quite confusing.

Our application requires a little bit of concurrency for a small amount of
time. As these words are quite subjective, I do a funny stress experiment
with sqlite3.

Considering all this, I have written a test application running on Linux
with sqlite3 library in serialized mode. My test application has 200
parallel threads in which 100 threads are executing SELECT * operation from
a table and 100 are executing update table (alternate fields in alternate
run) command in auto-commit mode (while(1)). I haven't verified the data
correctly written in database as I only rely on return code and I was
stress testing. I expect at some point it should produce SQLITE_BUSY
command at some point of time. But it didn't.

Only thing I got is:- while the test application is running, in a separate
SQLite command prompt I open the same database and executed .tables
command.  This time, I got a database locked error in my test application.

So my questions are:-

1. In auto-commit mode in serialized threading mode, how command queueing
works?
2. Multiple simultaneous calls to sqlite_exec() performing Multiple write
commands or read commands while write is in progress - will this be handled
by sqlite_exec() itself? Or does the application need to do some kind of
locking to avoid such situation as mentioned in the FAQ? In serialized
mode, sqlite3 implements its own locking, right? Do application need to do
a high level locking beyond this?
3. Will there be a case the database can become corrupt or some operations
missed to get performed in such a case?

Thank you,
Lullaby






On Fri, Apr 26, 2019, 9:07 PM Jens Alfke <j...@mooseyard.com> wrote:

>
>
> > On Apr 25, 2019, at 6:09 PM, Lullaby Dayal <lullaby.tec...@gmail.com>
> wrote:
> >
> > A single database connection is shared
> > among all these services. More than one service access the service API to
> > read/write database at the same time. No locking is implemented in our
> > service accessing the database.
>
> The one issue that comes to mind is transactions: your design has no
> isolation (the I in ACID) between threads.
>
> In more detail: if a thread executes "BEGIN", does some
> inserts/updates/deletes, and then executes "END", other threads that issue
> SQLite calls at the same time will see the uncommitted changes being made
> by the first thread. Depending on your design, this can cause problems,
> especially if the first thread ever ends up aborting the transaction
> (leaving the other threads with stale data that isn't in the database.)
>
> It gets even more "fun" if the secondary threads are making their own
> changes (without BEGIN/END), because those changes will become part of the
> first thread's transaction, so if the first thread aborts, the other
> threads' changes will be lost.
>
> For this reason it's usually good to have a mutex for transactions: you
> lock the mutex before calling BEGIN and unlock it after calling END. (If
> you make one-off changes without BEGIN/END, you have to lock the mutex
> around those calls too.)
>
> If this isn't a problem for you because you never use transactions, then
> you may have a different problem: write performance. Issuing multiple
> writes without a transaction is inefficient, because each write has to
> begin and commit its own transaction, and the commits tend to be expensive
> (depending on the filesystem) because they have to ensure durability.
>
> —Jens
> _______________________________________________
> sqlite-users mailing list
> sqlite-users@mailinglists.sqlite.org
> http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users
>
_______________________________________________
sqlite-users mailing list
sqlite-users@mailinglists.sqlite.org
http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users

Reply via email to