]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
When searching the wal file for a frame, do not search that part that was already...
authordan <dan@noemail.net>
Thu, 13 Aug 2015 20:23:46 +0000 (20:23 +0000)
committerdan <dan@noemail.net>
Thu, 13 Aug 2015 20:23:46 +0000 (20:23 +0000)
FossilOrigin-Name: 90760e72327eb0593cbfa6d7058b554198cd8044

manifest
manifest.uuid
src/wal.c

index ebe04a4a711bac6aff3058dbe04cc7589812531b..e20dbce2250e514107e5d32d178b3df30c8978ed 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Avoid\sreading\sframes\sthat\shave\salready\sbeen\scheckpointed\sfrom\sthe\swal\sfile.
-D 2015-08-12T19:42:08.239
+C When\ssearching\sthe\swal\sfile\sfor\sa\sframe,\sdo\snot\ssearch\sthat\spart\sthat\swas\salready\scheckpointed\swhen\sthe\ssnapshot\sbeing\sread\swas\sat\sthe\shead\sof\sthe\swal\sfile.
+D 2015-08-13T20:23:46.835
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 F Makefile.in 2fc9ca6bf5949d415801c007ed3004a4bdb7c380
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -408,7 +408,7 @@ F src/vdbesort.c f5009e7a35e3065635d8918b9a31f498a499976b
 F src/vdbetrace.c 8befe829faff6d9e6f6e4dee5a7d3f85cc85f1a0
 F src/vtab.c 082b35a25a26e3d36f365ca8cd73c1922532f05e
 F src/vxworks.h c18586c8edc1bddbc15c004fa16aeb1e1342b4fb
-F src/wal.c 9eb487483eed48310f999d9735263f33c71026b3
+F src/wal.c 8cd07f1f99e1a81346db1c9da879bef6c6f97cf6
 F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
 F src/walker.c c253b95b4ee44b21c406e2a1052636c31ea27804
 F src/where.c c745d3aa78ad1aa8982febb99f2f17ee5cbac069
@@ -1372,10 +1372,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b
 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
-P efb7c9c5d0015c8c966f8d6742c05cda82fc146a
-R 91c715455a10615960997cdbeb286182
-T *branch * wal-read-change
-T *sym-wal-read-change *
-T -sym-trunk *
+P 5669ac4a40429abc3f44540fc9d2f3b79b404bdf
+R 0be4044b3773f95bd61300112256d197
 U dan
-Z 265f3376267bf1285595a2e2dc6d13aa
+Z f0c98bb462164518b46029fee8374b58
index 52606f1923920086f1a14ca5103918c409d6af95..84745b0a24003f9a029d687b428326bbf2885835 100644 (file)
@@ -1 +1 @@
-5669ac4a40429abc3f44540fc9d2f3b79b404bdf
\ No newline at end of file
+90760e72327eb0593cbfa6d7058b554198cd8044
\ No newline at end of file
index 0e4d07d37205123a50e75d020c0c84428cc8b4a5..cf8f1d4e66460af2f63a78d464813037cbe8e1ca 100644 (file)
--- a/src/wal.c
+++ b/src/wal.c
@@ -428,6 +428,7 @@ struct Wal {
   u8 syncHeader;             /* Fsync the WAL header if true */
   u8 padToSectorBoundary;    /* Pad transactions out to the next sector */
   WalIndexHdr hdr;           /* Wal-index header for current transaction */
+  u32 minFrame;              /* Ignore wal frames before this one */
   const char *zWalName;      /* Name of WAL file */
   u32 nCkpt;                 /* Checkpoint sequence counter in the wal-header */
 #ifdef SQLITE_DEBUG
@@ -2296,12 +2297,27 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
     ** pWal->hdr.mxFrame risks reading a corrupted snapshot. So, retry
     ** instead.
     **
-    ** This does not guarantee that the copy of the wal-index header is up to
-    ** date before proceeding. That would not be possible without somehow
-    ** blocking writers. It only guarantees that a dangerous checkpoint or 
-    ** log-wrap (either of which would require an exclusive lock on
-    ** WAL_READ_LOCK(mxI)) has not occurred since the snapshot was valid.
+    ** Before checking that the live wal-index header has not changed
+    ** since it was read, set Wal.minFrame to the first frame in the wal
+    ** file that has not yet been checkpointed. This client will not need
+    ** to read any frames earlier than minFrame from the wal file - they
+    ** can be safely read directly from the database file.
+    **
+    ** Because a ShmBarrier() call is made between taking the copy of 
+    ** nBackfill and checking that the wal-header in shared-memory still
+    ** matches the one cached in pWal->hdr, it is guaranteed that the 
+    ** checkpointer that set nBackfill was not working with a wal-index
+    ** header newer than that cached in pWal->hdr. If it were, that could
+    ** cause a problem. The checkpointer could omit to checkpoint
+    ** a version of page X that lies before pWal->minFrame (call that version
+    ** A) on the basis that there is a newer version (version B) of the same
+    ** page later in the wal file. But if version B happens to like past
+    ** frame pWal->hdr.mxFrame - then the client would incorrectly assume
+    ** that it can read version A from the database file. However, since
+    ** we can guarantee that the checkpointer that set nBackfill could not
+    ** see any pages past pWal->hdr.mxFrame, this problem does not come up.
     */
+    pWal->minFrame = pInfo->nBackfill+1;
     walShmBarrier(pWal);
     if( pInfo->aReadMark[mxI]!=mxReadMark
      || memcmp((void *)walIndexHdr(pWal), &pWal->hdr, sizeof(WalIndexHdr))
@@ -2372,7 +2388,6 @@ int sqlite3WalFindFrame(
   u32 iRead = 0;                  /* If !=0, WAL frame to return data from */
   u32 iLast = pWal->hdr.mxFrame;  /* Last page in WAL for this reader */
   int iHash;                      /* Used to loop through N hash tables */
-  u32 iFirst;
   int iMinHash;
 
   /* This routine is only be called from within a read transaction. */
@@ -2384,10 +2399,7 @@ int sqlite3WalFindFrame(
   ** then the WAL is ignored by the reader so return early, as if the 
   ** WAL were empty.
   */
-  if( iLast==0 
-   || pWal->readLock==0 
-   || iLast==(iFirst = walCkptInfo(pWal)->nBackfill)
-  ){
+  if( iLast==0 || pWal->readLock==0 ){
     *piRead = 0;
     return SQLITE_OK;
   }
@@ -2417,7 +2429,7 @@ int sqlite3WalFindFrame(
   **     This condition filters out entries that were added to the hash
   **     table after the current read-transaction had started.
   */
-  iMinHash = walFramePage(iFirst);
+  iMinHash = walFramePage(pWal->minFrame);
   for(iHash=walFramePage(iLast); iHash>=iMinHash && iRead==0; iHash--){
     volatile ht_slot *aHash;      /* Pointer to hash table */
     volatile u32 *aPgno;          /* Pointer to array of page numbers */
@@ -2433,7 +2445,7 @@ int sqlite3WalFindFrame(
     nCollide = HASHTABLE_NSLOT;
     for(iKey=walHash(pgno); aHash[iKey]; iKey=walNextHash(iKey)){
       u32 iFrame = aHash[iKey] + iZero;
-      if( iFrame<=iLast && iFrame>iFirst && aPgno[aHash[iKey]]==pgno ){
+      if( iFrame<=iLast && iFrame>=pWal->minFrame && aPgno[aHash[iKey]]==pgno ){
         assert( iFrame>iRead || CORRUPT_DB );
         iRead = iFrame;
       }