A cyclical WAL file has this problem:

You can never be sure when is the right time to wrap around.
If you wrap around too early, you run the risk of hitting the wall
put up by the earliest reader, who is still using the end of the
WAL file. In which case the writer would have to block on the reader,
which is something that the current system doesn't suffer from.
My guess is that a very high proportion of use cases would never
suffer this issue, provided they set an appropriate wrap around size
but this does place that burden on the implementer - of picking
the right heuristics.

It is a pathological case, but imagine an implementer never tests
for this wraparound issue, and builds a deadlock into his app
that arises when a writer blocks on a reader. This is the kind of
unexpected behaviour that could really bite you.

The only solution around this would be to have more than 1 WAL file.
To avoid hitting this same problem with multiple WAL files, you'd
need to support an arbitrary N number of WAL files. And that,
undoubtedly, is a more complex implementation than what currently
exists. I imagine it's quite a task for the SQLite developers to
get 100% branch test coverage.

On one system of mine, where blocking is an issue, I
buffer up the write messages, and flush them on a background thread.
Of course this may not be practical for you...

Ben

-----Original Message-----
From: sqlite-users-boun...@sqlite.org [mailto:sqlite-users-boun...@sqlite.org] 
On Behalf Of Yoni
Sent: 24 November 2010 04:46 PM
To: sqlite-users@sqlite.org
Subject: [sqlite] WAL file size

Hi,

I am currently developing a system, which have the following requirements:
1. should be very fast and responsive
2. run forever (or at least a very long time) without restart.
3. have steady stream of writes to the DB.

Currently I am using sqlite with one sql connection, and I run sql 
checkpoint every once in a while (e.g. after 5 minutes, or after 10000 
inserts to the DB) - I don't use auto checkpoint.
Since I run the checkpoint in the main thread, the system is 
unresponsive for a long time (can take from 400ms to 20000ms!)

What I would like to do, is to run the checkpoint in another thread, so 
the main thread can keep working (and using sql), and do the long 
checkpoint work in the background.

The problem is that when I try to do it, the WAL file grows without limit.
I wrote a little program that do exactly this (insert rows as fast as C 
allows, and in the background run checkpoints).
The result (after 30 secs and 400K records) was: DB size 19MB and WAL 
size 451MB! (tried on linux Debian with sqlite 3.7.2, and on winXP with 
same sqlite version).

I think that the problem relies on the fact the during the checkpoint, I 
keep writing to the WAL file, thus the checkpoint can never get to the 
end of the file. And since WAL file is not cyclic, it will grow forever, 
leaving the most of the file unused (the beginning), and using only the 
end of the file for real data.

I found this thread 
http://www.mail-archive.com/sqlite-users@sqlite.org/msg56074.html, 
discussing a similar problem, and also saw dan's commit 
(http://www.sqlite.org/src/info/72787c010c) approaching the same 
problem, but not solving it, since it requires to block all DB activity.

I think this can be fixed, if sqlite use a cyclic WAL file.
I found that PostgreSQL also bumped into this, and used multiple WAL 
files, in order to avoid this kind of problem 
(http://www.sql.org/sql-database/postgresql/manual/wal-implementation.html).
Now, we do not need multiple files to do it, we just need to write to 
the beginning of the WAL file, when we have enough space (e.g. at least 
16MB of unused space - configurable).
So the WAL file might look like this:

                     logical end           logical start
                          |                    |
                          V                    V
------------------------------------------------------------------
header | committed data  | unused space       | committed data   |==>
------------------------------------------------------------------  |
        ^                                                            |
         ============================================================|

when the data at the head of the file is logically at the end of it.

When the writing is too fast, eventually they will get to logical start 
of the file. in this point we can force a blocking checkpoint, since 
this situation is very rare.

This will allow limiting WAL file size, while avoiding blocking 
checkpoint, and will increase responsiveness significantly!

Yoni.
_______________________________________________
sqlite-users mailing list
sqlite-users@sqlite.org
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users


_______________________________________________
sqlite-users mailing list
sqlite-users@sqlite.org
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users

Reply via email to