/ Check-in [9a429349]
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:Avoid unnecessary page cache allocations when move a page while autovacuuming an in-memory database, since the allocation might fail making it impossible to rollback the transaction.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 9a429349ccc2fa9acd28365a86578f602e87dafb
User & Date: drh 2009-11-20 13:18:14
References
2009-11-20
18:51 Fixed ticket [564d412f]: OOM on autovacuum of in-memory database causes problems. plus 3 other changes artifact: 3ed1331e user: drh
Context
2009-11-20
17:18
Add a test to make sure a database can be attached to a single handle twice if not in shared-cache mode. check-in: 1c4984c6 user: dan tags: trunk
15:02
If the root pages numbers of the internal schema are adjusted due to autovacuum on a DROP TABLE statement and that statement later aborts (for example, due to an OOM error) then reset the internal schema at the conclusion of the statement. Partial fix for ticket [564d412f15a]. check-in: e493b093 user: drh tags: trunk
13:18
Avoid unnecessary page cache allocations when move a page while autovacuuming an in-memory database, since the allocation might fail making it impossible to rollback the transaction. check-in: 9a429349 user: drh tags: trunk
05:05
Improve comments and other things in fts3_write.c. check-in: 1cf0e3cc user: dan tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/pager.c.

5150
5151
5152
5153
5154
5155
5156






5157

5158
5159
5160
5161
5162
5163
5164
....
5195
5196
5197
5198
5199
5200
5201
5202
5203
5204
5205
5206
5207
5208
5209
5210
5211
5212
5213
5214
5215
5216
5217
5218
5219
5220
  ** for the page moved there.
  */
  pPg->flags &= ~PGHDR_NEED_SYNC;
  pPgOld = pager_lookup(pPager, pgno);
  assert( !pPgOld || pPgOld->nRef==1 );
  if( pPgOld ){
    pPg->flags |= (pPgOld->flags&PGHDR_NEED_SYNC);






    sqlite3PcacheDrop(pPgOld);

  }

  origPgno = pPg->pgno;
  sqlite3PcacheMove(pPg, pgno);
  sqlite3PcacheMakeDirty(pPg);
  pPager->dbModified = 1;

................................................................................
    pPgHdr->flags |= PGHDR_NEED_SYNC;
    sqlite3PcacheMakeDirty(pPgHdr);
    sqlite3PagerUnref(pPgHdr);
  }

  /*
  ** For an in-memory database, make sure the original page continues
  ** to exist, in case the transaction needs to roll back.  We allocate
  ** the page now, instead of at rollback, because we can better deal
  ** with an out-of-memory error now.  Ticket #3761.
  */
  if( MEMDB ){
    DbPage *pNew;
    rc = sqlite3PagerAcquire(pPager, origPgno, &pNew, 1);
    if( rc!=SQLITE_OK ){
      sqlite3PcacheMove(pPg, origPgno);
      return rc;
    }
    sqlite3PagerUnref(pNew);
  }

  return SQLITE_OK;
}
#endif

/*







>
>
>
>
>
>
|
>







 







|
|
<


<
<
<
|
<
<
|







5150
5151
5152
5153
5154
5155
5156
5157
5158
5159
5160
5161
5162
5163
5164
5165
5166
5167
5168
5169
5170
5171
....
5202
5203
5204
5205
5206
5207
5208
5209
5210

5211
5212



5213


5214
5215
5216
5217
5218
5219
5220
5221
  ** for the page moved there.
  */
  pPg->flags &= ~PGHDR_NEED_SYNC;
  pPgOld = pager_lookup(pPager, pgno);
  assert( !pPgOld || pPgOld->nRef==1 );
  if( pPgOld ){
    pPg->flags |= (pPgOld->flags&PGHDR_NEED_SYNC);
    if( MEMDB ){
      /* Do not discard pages from an in-memory database since we might
      ** need to rollback later.  Just move the page out of the way. */
      assert( pPager->dbSizeValid );
      sqlite3PcacheMove(pPgOld, pPager->dbSize+1);
    }else{
      sqlite3PcacheDrop(pPgOld);
    }
  }

  origPgno = pPg->pgno;
  sqlite3PcacheMove(pPg, pgno);
  sqlite3PcacheMakeDirty(pPg);
  pPager->dbModified = 1;

................................................................................
    pPgHdr->flags |= PGHDR_NEED_SYNC;
    sqlite3PcacheMakeDirty(pPgHdr);
    sqlite3PagerUnref(pPgHdr);
  }

  /*
  ** For an in-memory database, make sure the original page continues
  ** to exist, in case the transaction needs to roll back.  Use pPgOld
  ** as the original page since it has already been allocated.

  */
  if( MEMDB ){



    sqlite3PcacheMove(pPgOld, origPgno);


    sqlite3PagerUnref(pPgOld);
  }

  return SQLITE_OK;
}
#endif

/*

Changes to src/pcache1.c.

661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
  }
  *pp = pPage->pNext;

  h = iNew%pCache->nHash;
  pPage->iKey = iNew;
  pPage->pNext = pCache->apHash[h];
  pCache->apHash[h] = pPage;

  /* The xRekey() interface is only used to move pages earlier in the
  ** database file (in order to move all free pages to the end of the
  ** file where they can be truncated off.)  Hence, it is not possible
  ** for the new page number to be greater than the largest previously
  ** fetched page.  But we retain the following test in case xRekey()
  ** begins to be used in different ways in the future.
  */
  if( NEVER(iNew>pCache->iMaxKey) ){
    pCache->iMaxKey = iNew;
  }

  pcache1LeaveMutex();
}

/*







<
<
<
<
<
<
<
<
|







661
662
663
664
665
666
667








668
669
670
671
672
673
674
675
  }
  *pp = pPage->pNext;

  h = iNew%pCache->nHash;
  pPage->iKey = iNew;
  pPage->pNext = pCache->apHash[h];
  pCache->apHash[h] = pPage;








  if( iNew>pCache->iMaxKey ){
    pCache->iMaxKey = iNew;
  }

  pcache1LeaveMutex();
}

/*