After throughout analysis of my original problem I have probably found
the culprit.

The problem happens when incremental_vacuum (incrVacuumStep) tries to
remove the last page and the last page is free list leaf. In that case
the following code path is taken:

        /* Remove the page from the files free-list. This is not required
        ** if nFin is non-zero. In that case, the free-list will be
        ** truncated to zero after this function returns, so it doesn't
        ** matter if it still contains some garbage entries.
        */
        Pgno iFreePg;
        MemPage *pFreePg;
        rc = allocateBtreePage(pBt, &pFreePg, &iFreePg, iLastPg, 1);

The allocateBtreePage searches the free list for the leaf page. Since
the page happens to located at the end of the free list all the trunk
pages have to be walked through. For each of the trunk pages that
contain pointer to at least one leaf page the following code is hit:

        /* Extract a leaf from the trunk */
        u32 closest;
        Pgno iPage;
        unsigned char *aData = pTrunk->aData;
        rc = sqlite3PagerWrite(pTrunk->pDbPage);
        if( rc ){
          goto end_allocate_page;
        }

Now the problem is that sqlite3PagerWrite is called regardless of
whether the page is modified or not. So most of the free list trunk
pages end up being marked as dirty and get to the journal / WAL even
though they weren't changed at all. This makes the journal / WAL grow
to several megabytes instead of less than 4 kilobytes in my case.

My proposed solution is to move the sqlite3PagerWrite call just before
the code that actually modifies the page, as in the patch below.

Best regards,
Filip Navara

--- old\btree.c 2011-01-28 08:15:16.000000000 +0100
+++ btree.c     2011-04-07 10:57:07.052116400 +0200
@@ -4893,10 +4893,6 @@
         u32 closest;
         Pgno iPage;
         unsigned char *aData = pTrunk->aData;
-        rc = sqlite3PagerWrite(pTrunk->pDbPage);
-        if( rc ){
-          goto end_allocate_page;
-        }
         if( nearby>0 ){
           u32 i;
           int dist;
@@ -4928,6 +4924,10 @@
           TRACE(("ALLOCATE: %d was leaf %d of %d on trunk %d"
                  ": %d more free pages\n",
                  *pPgno, closest+1, k, pTrunk->pgno, n-1));
+          rc = sqlite3PagerWrite(pTrunk->pDbPage);
+          if( rc ){
+            goto end_allocate_page;
+          }
           if( closest<k-1 ){
             memcpy(&aData[8+closest*4], &aData[4+k*4], 4);
           }
_______________________________________________
sqlite-users mailing list
sqlite-users@sqlite.org
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users

Reply via email to