Hi Richard, Thanks for the quick response. I wrote a little program that demonstrate the error (below). It opens a new DB, create a table, and start an endless loop of INSERT's. In a background thread it performs a wal checkpoint. There is no difference in WAL file size - with or without transactions (passed by argument to the program). This is the result after 45 seconds: -rw-r--r-- 1 1.0K 2010-08-10 11:41 test.db -rw-r--r-- 1 1.1G 2010-08-10 11:42 test.db-wal -rw-r--r-- 1 8.0M 2010-08-10 11:42 test.db-shm
Program compiled with GCC on debian lenny, using sqlite 3.7.0. #include "sqlite3.h" #include "stdio.h" #include "stdlib.h" #include "fcntl.h" static void sql_exec(sqlite3 *conn, char *query) { char *err; if (sqlite3_exec(conn, query, NULL, 0, &err)) { printf("sqlite: failed exec %s. err: %s\n", query, err); exit(1); } } static sqlite3 *sql_open_conn(void) { sqlite3 *conn; if (sqlite3_open_v2("test.db", &conn, SQLITE_OPEN_READWRITE, NULL)) { printf("sqlite3_open_v2 failed\n"); exit(1); } return conn; } static int do_checkpoint() { sqlite3 *conn; while (1) { sleep(2); printf("calling wal checkpoint\n"); fflush(0); conn = sql_open_conn(); if (sqlite3_wal_checkpoint(conn, NULL)) { printf("sqlite3_wal_autocheckpoint failed\n"); exit(1); } sqlite3_close(conn); } } int main(int argc, char **argv) { sqlite3 *conn = NULL; char *err_msg = NULL; pthread_t thread; int fd, i, use_transactions = 0; time_t start; if (argc>1) use_transactions = atoi(argv[1]); printf("use_transactions=%d\n", use_transactions); printf("Start\n"); if (unlink("test.db") || unlink("test.db-wal")) { printf("failed unlink test.db\n"); exit(1); } fd = open("test.db", O_CREAT|O_RDWR, 0666); if (fd<0) { printf("could not open test.db\n"); exit(1); } close(fd); conn = sql_open_conn(); sqlite3_enable_shared_cache(1); sql_exec(conn, "PRAGMA journal_mode=WAL"); sql_exec(conn, "PRAGMA synchronous=normal"); sql_exec(conn, "PRAGMA temp_store=memory"); sql_exec(conn, "PRAGMA wal_autocheckpoint=-1"); sql_exec(conn, "create table tbl1 (one varchar(20), two varchar(20))"); if (pthread_create(&thread, NULL, do_checkpoint, NULL)) { printf("could not start thread\n"); exit(1); } start = time(); if (use_transactions) sql_exec(conn, "BEGIN TRANSACTION"); while (1) { if (use_transactions && !(i++%100000)) { printf("END BEGIN transactions\n"); fflush(stdout); sql_exec(conn, "END TRANSACTION"); sql_exec(conn, "BEGIN TRANSACTION"); } sql_exec(conn, "INSERT INTO tbl1 values('aaaaaaaaaaaaaaaaaaa', " "'bbbbbbbbbbbbbbbbbbb')"); } if (use_transactions) sql_exec(conn, "END TRANSACTION"); sqlite3_close(conn); printf("Finished\n"); return 0; } On Tue, Aug 10, 2010 at 9:36 AM, Richard Hipp <d...@sqlite.org> wrote: > On Tue, Aug 10, 2010 at 2:24 AM, Yoni Londner <yonih...@gmail.com> wrote: > > > Hello, > > I have a questions about the correct use of transactions and WAL. > > > > I am writing an application that: > > 1. should very fast > > 2. should be very responsive > > 3. don't care if the last N minutes of data will be lost (but DB should > > never be corrupted) > > > > What I tried to do: > > 1. open a transactions and close it every 3 minutes (So most of the tune > > all work is on memory, and thus is very fast) > > 2. disable wal auto checkpoint (So I wont have very slow queries due to > a > > checkpoint) > > 3. run wal checkpoint in another thread (with another connection) - so > it > > wont affect the responsiveness of the main thread. > > > > Results: > > 1. process memory is increasing with no upper limit > > 2. eventually I get an I/O error > > > > I'm guessing your write transactions are preventing the checkpoint from > running to completion. Hence, the WAL grows without bound and the > wal-index > (an in-memory structure proportional in size to the WAL file) eventually > uses up all memory. > > Set PRAGMA synchronous=NORMAL. This prevents all fsync() calls on the > writer thread at the cost of durability, which you say you don't care > about. > Omit the 3-minute transactions, allowing each write to be its own > transaction. Writes then will still be in-memory (if you count the > operating system filesystem cache as "in-memory"). But then the > checkpoints > will be able to run and keep the size of the WAL file under control. > > > > > > > Questions: > > 1. what am I doing wrong. > > 2. what is the correct way to achieve the goals I mentioned before. > > > > Thanks, > > Jon. > > _______________________________________________ > > sqlite-users mailing list > > sqlite-users@sqlite.org > > http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users > > > > > > -- > D. Richard Hipp > d...@sqlite.org > _______________________________________________ > 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