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