Yes! The journal file was indeed there. I deleted it before openning the database, and read 50 records. I repeated the process; it's consistent.
The way I see it that even though the synchronous setting is FULL, there is no API to tell the OS to physically delete a file from disk, just like there is no API to physically force a file to truncate. Well, maybe there is a way (or an API), but sqlite doesn't presently do it. The only way sqlite forces physical writes to disk is via FlushFileBuffers(). So with: journal_mode=DELETE: no buffers written, the OS delays in deleting the file, and during a hard reset, the journal file will remain -- and in my case, that's causing 1 record to get lost. journal_mode=TRUNCATE: no buffers written, the OS delays in truncating the file; same as above. journal_mode=PERSIST: header information is physically written to disk. journal_mode=WAL (synchronous=FULL): all data is physically written to disk, no journal files are truncated or deleted. I think your asking the question indicates you suspected what I would find, no? If I don't opt for WAL, I will use the PERSIST mode instead of the default DELETE mode. On Mon, Sep 10, 2012 at 6:47 AM, Dan Kennedy <danielk1...@gmail.com> wrote: > On 09/10/2012 03:15 AM, Daniel Frimerman wrote: > >> My apologies about the attachment; should have known better. >> This should be better: >> https://dl.dropbox.com/u/**50838941/SQLite3_Test.zip<https://dl.dropbox.com/u/50838941/SQLite3_Test.zip> >> >> I only get the problem with DELETE and TRUNCATE journal_mode (synchronous >> set to NORMAL or FULL), but not with PERSIST (synchronous set to NORMAL or >> FULL) or WAL (synchronous set to FULL). >> > > When using "PRAGMA journal_mode=DELETE", after you reboot the > system is there a *-journal file present in the directory > next to your database file? > > If so and you rename it before opening the database, are all > 50 records present? > > > > >> The reason I think there has to be 50 rows is because on FULL mode for >> example, the I/O buffers are flushed, and it's consistently missing 1 >> record as opposed to any other number of records. I insert 50 records, the >> sqlite3 command line utility executes the script, and I get to a stage >> where I can write commands to the console. What I mean is that as far as >> sqlite is concerned, it has written the data to disk and also instructed >> the OS to flush the buffers. Perhaps it finalises something from the last >> insert only when the next insert comes in? >> It could be a coincidence of some sort, by sheer difference of >> implementation of different journals that the "problem" doesn't show >> itself >> with PERSIST or WAL journals. >> >> I turned off host I/O cache in VirtualBox, so any writes by the guest OS >> have to be physically written to the virtual disk on the host. The guest >> has "standard" I/O caching on disk, but FlushFileBuffers() should have >> done >> its job. There is no reason why any link in the chain should report data >> written to disk without actually doing it, unless there is a problem. >> >> I suppose I should just go ahead and test it on the physical PC. If there >> is a problem with that also, then I suppose I could blame the OS for not >> flushing stuff to disk properly. >> >> Now I gotta find me a machine............ >> >> Regards, >> >> Dan >> >> >> >> On Sun, Sep 9, 2012 at 8:14 PM, Pavel Ivanov<paiva...@gmail.com> wrote: >> >> Note: attachments are stripped out of this list. So if you want for >>> anybody else to see your zip file you need to put it on some website >>> and post link here. >>> >>> About the problem you have: I wonder how are you sure that there >>> should be 50 rows in the database and not 49? If you are resetting the >>> OS before it has a chance to properly commit everything then it's okay >>> for last transaction to be missing. But if you are sure that you are >>> resetting the OS after everything is settled then maybe you are not >>> committing your last transaction properly? Or maybe there's some bug >>> in your virtualization layer and you need to try the same thing on a >>> real hardware? >>> >>> >>> Pavel >>> >>> >>> On Sun, Sep 9, 2012 at 8:50 AM, Daniel Frimerman >>> <danielfrimer...@gmail.com> wrote: >>> >>>> I am fairly new to sqlite and as a result of not reading the manual and >>>> >>> not >>> >>>> doing some performance testing, I got punished somewhat. I did not >>>> anticipate that on journal_mode=DELETE and synchronous=FULL, I would get >>>> >>> no >>> >>>> more than 5 inserts (in auto-commit mode) per second. It crippled a >>>> certain batch operation on a live system. That's water under the >>>> bridge; >>>> it's the testing afterwards and a potential minor problem that I found >>>> is >>>> what I am now interested in. >>>> >>>> I tested all journal mode settings for sqlite, as well as the >>>> synchronous >>>> setting. Some things that I discovered were not so obvious from reading >>>> the docs, such as the WAL journal mode combined with NORMAL synchronous >>>> setting, which is nowhere near as "durable" as NORMAL setting for other >>>> journal modes. I.e. NORMAL mode for DELETE journal in 99% of cases saves >>>> all inserted data - reproducing the slightest of chances that >>>> consistency >>>> is compromised was rather hard. This is reflected in performance >>>> >>> testing: >>> >>>> NORMAL is only slightly faster than FULL mode for non-WAL journal >>>> >>> settings >>> >>>> (btw, journal_mode=OFF was never tested in any of my tests). But, I >>>> understood, that in WAL+NORMAL mode is equivalent to FULL+non-WAL mode >>>> where consistency/corruption is concerned. That is, the database cannot >>>> get corrupted in WAL+NORMAL. The gain in speed for WAL+NORMAL trades >>>> off >>>> durability and in my tests I easily reproduced that. >>>> >>>> Okay, that was not really related to the possible bug I found. I've >>>> attached a ZIP file containing some batch files that create a table, >>>> >>> insert >>> >>>> some rows, at which point you hard-reset the OS, log back in and check >>>> if >>>> the number of rows in the DB matches what you inserted. Although the >>>> non-WAL journal modes are somewhat similar, the little problem that I've >>>> come to find only happens on DELETE/TRUNCATE, but not on PERSIST or WAL. >>>> The problem is basically as follows: in DELETE and TRUNCATE journal mode >>>> combined with NORMAL/FULL synchronous mode, there is always 1 row >>>> missing >>>> during my simulated power-cut. >>>> >>>> I used VirtualBox 4.1.22 and Windows XP Pro (SP3) and sqlite3 3.7.14 >>>> (command line as well as through my testing application). In VirtualBox, >>>> under storage settings for the VM, I used IDE Controller (afaik it's >>>> >>> single >>> >>>> threaded), turned off host I/O cache. Inside the guest, write-cache >>>> >>> should >>> >>>> be enabled in device manager under policies for the default disk >>>> >>> controller. >>> >>>> >>>> To test this, set your VM as above, copy the files from the attached ZIP >>>> file, also download the latest sqlite3 command line shell. Restart the >>>> guest once to ensure your files are flushed out before you start >>>> >>> resetting >>> >>>> the guest :) >>>> Execute the following batch file: EXEC_DATA__DELETE_FULL.cmd, wait 2-3 >>>> seconds (or less) then hit HOST+R to hard reset the OS. When you >>>> reboot, >>>> run READ_DATA.cmd, you'll see 49 rows, but there should be 50. >>>> You can try the same with EXEC_DATA__DELETE_NORMAL.cmd, >>>> EXEC_DATA__TRUNCATE_FULL.cmd, EXEC_DATA__TRUNCATE_NORMAL.cmd >>>> 50 rows if you try with EXEC_DATA__PERSIST_FULL.cmd and >>>> EXEC_DATA__PERSIST_NORMAL.cmd and EXEC_DATA__WAL_FULL.cmd >>>> >>>> What's with that? >>>> >>>> Kind regards, Dan >>>> >>>> ______________________________**_________________ >>>> sqlite-users mailing list >>>> sqlite-users@sqlite.org >>>> http://sqlite.org:8080/cgi-**bin/mailman/listinfo/sqlite-**users<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<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<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<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