/ Check-in [a55eb4c3]
Login
SQLite training in Houston TX on 2019-11-05 (details)
Part of the 2019 Tcl Conference

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Disable memory-pressure induced cache spill during savepoint rollback.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: a55eb4c3e9fa4ea43b8f8182eb9e39138df03f52
User & Date: drh 2010-06-24 14:52:25
Context
2010-06-24
17:37
Modify ctime.test to work with SQLITE_THREADSAFE=2. check-in: c6db3b30 user: dan tags: trunk
14:52
Disable memory-pressure induced cache spill during savepoint rollback. check-in: a55eb4c3 user: drh tags: trunk
13:24
Add a coverage test to pagerfault.test. check-in: b58db67e user: dan tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/pager.c.

   301    301   **   then attempts to upgrade to an exclusive lock. If this attempt
   302    302   **   fails, then SQLITE_BUSY may be returned to the user and the user
   303    303   **   may attempt to commit the transaction again later (calling
   304    304   **   CommitPhaseOne() again). This flag is used to ensure that the 
   305    305   **   master journal name is only written to the journal file the first
   306    306   **   time CommitPhaseOne() is called.
   307    307   **
   308         -** doNotSync
          308  +** doNotSpill
   309    309   **
   310    310   **   When enabled, cache spills are prohibited and the journal file cannot
   311    311   **   be synced.  This variable is set and cleared by sqlite3PagerWrite() 
   312    312   **   in order to prevent a journal sync from happening in between the
   313         -**   journalling of two pages on the same sector.
          313  +**   journalling of two pages on the same sector.  It is also set to prevent
          314  +**   pagerStress() from trying to use the journal during a rollback.
   314    315   **
   315    316   ** needSync
   316    317   **
   317    318   **   TODO: It might be easier to set this variable in writeJournalHdr()
   318    319   **   and writeMasterJournal() only. Change its meaning to "unsynced data
   319    320   **   has been written to the journal".
   320    321   **
................................................................................
   350    351     */
   351    352     u8 state;                   /* PAGER_UNLOCK, _SHARED, _RESERVED, etc. */
   352    353     u8 dbModified;              /* True if there are any changes to the Db */
   353    354     u8 needSync;                /* True if an fsync() is needed on the journal */
   354    355     u8 journalStarted;          /* True if header of journal is synced */
   355    356     u8 changeCountDone;         /* Set after incrementing the change-counter */
   356    357     u8 setMaster;               /* True if a m-j name has been written to jrnl */
   357         -  u8 doNotSync;               /* Boolean. While true, do not spill the cache */
          358  +  u8 doNotSpill;              /* Do not spill the cache when non-zero */
   358    359     u8 dbSizeValid;             /* Set when dbSize is correct */
   359    360     u8 subjInMemory;            /* True to use in-memory sub-journals */
   360    361     Pgno dbSize;                /* Number of pages in the database */
   361    362     Pgno dbOrigSize;            /* dbSize before the current transaction */
   362    363     Pgno dbFileSize;            /* Number of pages in the database file */
   363    364     int errCode;                /* One of several kinds of errors */
   364    365     int nRec;                   /* Pages journalled since last j-header written */
................................................................................
  1686   1687       **
  1687   1688       ** The solution is to add an in-memory page to the cache containing
  1688   1689       ** the data just read from the sub-journal. Mark the page as dirty 
  1689   1690       ** and if the pager requires a journal-sync, then mark the page as 
  1690   1691       ** requiring a journal-sync before it is written.
  1691   1692       */
  1692   1693       assert( isSavepnt );
  1693         -    if( (rc = sqlite3PagerAcquire(pPager, pgno, &pPg, 1))!=SQLITE_OK ){
  1694         -      return rc;
  1695         -    }
         1694  +    assert( pPager->doNotSpill==0 );
         1695  +    pPager->doNotSpill++;
         1696  +    rc = sqlite3PagerAcquire(pPager, pgno, &pPg, 1);
         1697  +    assert( pPager->doNotSpill==1 );
         1698  +    pPager->doNotSpill--;
         1699  +    if( rc!=SQLITE_OK ) return rc;
  1696   1700       pPg->flags &= ~PGHDR_NEED_READ;
  1697   1701       sqlite3PcacheMakeDirty(pPg);
  1698   1702     }
  1699   1703     if( pPg ){
  1700   1704       /* No page should ever be explicitly rolled back that is in use, except
  1701   1705       ** for page 1 which is held in use in order to keep the lock on the
  1702   1706       ** database active. However such a page may be rolled back as a result
................................................................................
  3509   3513   */
  3510   3514   static int pagerStress(void *p, PgHdr *pPg){
  3511   3515     Pager *pPager = (Pager *)p;
  3512   3516     int rc = SQLITE_OK;
  3513   3517   
  3514   3518     assert( pPg->pPager==pPager );
  3515   3519     assert( pPg->flags&PGHDR_DIRTY );
         3520  +
         3521  +  /* The doNotSpill flag is set during times when writing to the journal
         3522  +  ** is disallowed:  (1) during calls to sqlite3PagerWrite() while it
         3523  +  ** is journalling a set of two or more database pages that are stored
         3524  +  ** on the same disk sector, and (2) while performing a rollback.
         3525  +  **
         3526  +  ** Similarly, if the pager has already entered the error state, do not
         3527  +  ** try to write the contents of pPg to disk.
         3528  +  */
         3529  +  if( pPager->errCode || pPager->doNotSpill ){
         3530  +    return SQLITE_OK;
         3531  +  }
  3516   3532   
  3517   3533     pPg->pDirty = 0;
  3518   3534     if( pagerUseWal(pPager) ){
  3519   3535       /* Write a single frame for this page to the log. */
  3520   3536       if( subjRequiresPage(pPg) ){ 
  3521   3537         rc = subjournalPage(pPg); 
  3522   3538       }
  3523   3539       if( rc==SQLITE_OK ){
  3524   3540         rc = pagerWalFrames(pPager, pPg, 0, 0, 0);
  3525   3541       }
  3526   3542     }else{
  3527         -    /* The doNotSync flag is set by the sqlite3PagerWrite() function while it
  3528         -    ** is journalling a set of two or more database pages that are stored
  3529         -    ** on the same disk sector. Syncing the journal is not allowed while
  3530         -    ** this is happening as it is important that all members of such a
  3531         -    ** set of pages are synced to disk together. So, if the page this function
  3532         -    ** is trying to make clean will require a journal sync and the doNotSync
  3533         -    ** flag is set, return without doing anything. The pcache layer will
  3534         -    ** just have to go ahead and allocate a new page buffer instead of
  3535         -    ** reusing pPg.
  3536         -    **
  3537         -    ** Similarly, if the pager has already entered the error state, do not
  3538         -    ** try to write the contents of pPg to disk.
  3539         -    */
  3540         -    if( pPager->errCode || (pPager->doNotSync && pPg->flags&PGHDR_NEED_SYNC) ){
  3541         -      return SQLITE_OK;
  3542         -    }
  3543   3543     
  3544   3544       /* Sync the journal file if required. */
  3545   3545       if( pPg->flags&PGHDR_NEED_SYNC ){
  3546   3546         rc = syncJournal(pPager);
  3547   3547         if( rc==SQLITE_OK && pPager->fullSync && 
  3548   3548           !(pPager->journalMode==PAGER_JOURNALMODE_MEMORY) &&
  3549   3549           !(sqlite3OsDeviceCharacteristics(pPager->fd)&SQLITE_IOCAP_SAFE_APPEND)
................................................................................
  4830   4830     if( nPagePerSector>1 ){
  4831   4831       Pgno nPageCount;          /* Total number of pages in database file */
  4832   4832       Pgno pg1;                 /* First page of the sector pPg is located on. */
  4833   4833       int nPage;                /* Number of pages starting at pg1 to journal */
  4834   4834       int ii;                   /* Loop counter */
  4835   4835       int needSync = 0;         /* True if any page has PGHDR_NEED_SYNC */
  4836   4836   
  4837         -    /* Set the doNotSync flag to 1. This is because we cannot allow a journal
         4837  +    /* Set the doNotSpill flag to 1. This is because we cannot allow a journal
  4838   4838       ** header to be written between the pages journaled by this function.
  4839   4839       */
  4840   4840       assert( !MEMDB );
  4841         -    assert( pPager->doNotSync==0 );
  4842         -    pPager->doNotSync = 1;
         4841  +    assert( pPager->doNotSpill==0 );
         4842  +    pPager->doNotSpill++;
  4843   4843   
  4844   4844       /* This trick assumes that both the page-size and sector-size are
  4845   4845       ** an integer power of 2. It sets variable pg1 to the identifier
  4846   4846       ** of the first page of the sector pPg is located on.
  4847   4847       */
  4848   4848       pg1 = ((pPg->pgno-1) & ~(nPagePerSector-1)) + 1;
  4849   4849   
................................................................................
  4897   4897             pPage->flags |= PGHDR_NEED_SYNC;
  4898   4898             sqlite3PagerUnref(pPage);
  4899   4899           }
  4900   4900         }
  4901   4901         assert(pPager->needSync);
  4902   4902       }
  4903   4903   
  4904         -    assert( pPager->doNotSync==1 );
  4905         -    pPager->doNotSync = 0;
         4904  +    assert( pPager->doNotSpill==1 );
         4905  +    pPager->doNotSpill--;
  4906   4906     }else{
  4907   4907       rc = pager_write(pDbPage);
  4908   4908     }
  4909   4909     return rc;
  4910   4910   }
  4911   4911   
  4912   4912   /*