/ Check-in [5190d84a]
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 locking shm-lock WAL_READ_LOCK(0) during recovery. Doing this allows recovery to proceed while a readonly_shm connection in unlocked mode has an ongoing read transaction.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | readonly-wal-recovery
Files: files | file ages | folders
SHA3-256: 5190d84a296b7cf716ef43bf7b6d4d351ef1a4d650de37dc01a5ab333da7c05d
User & Date: dan 2017-11-02 11:12:03
Context
2017-11-02
18:57
Fix test cases in wal2.test broken by the locking change in the previous commit. check-in: f569c351 user: dan tags: readonly-wal-recovery
11:12
Avoid locking shm-lock WAL_READ_LOCK(0) during recovery. Doing this allows recovery to proceed while a readonly_shm connection in unlocked mode has an ongoing read transaction. check-in: 5190d84a user: dan tags: readonly-wal-recovery
2017-11-01
20:59
If a readonly_shm connection cannot map the *-shm file because no other process is holding the DMS lock, have it read from the database file only, ignoring any content in the wal file. check-in: ce5d13c2 user: dan tags: readonly-wal-recovery
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/wal.c.

  1097   1097   ** the necessary locks, this routine returns SQLITE_BUSY.
  1098   1098   */
  1099   1099   static int walIndexRecover(Wal *pWal){
  1100   1100     int rc;                         /* Return Code */
  1101   1101     i64 nSize;                      /* Size of log file */
  1102   1102     u32 aFrameCksum[2] = {0, 0};
  1103   1103     int iLock;                      /* Lock offset to lock for checkpoint */
  1104         -  int nLock;                      /* Number of locks to hold */
  1105   1104   
  1106   1105     /* Obtain an exclusive lock on all byte in the locking range not already
  1107   1106     ** locked by the caller. The caller is guaranteed to have locked the
  1108   1107     ** WAL_WRITE_LOCK byte, and may have also locked the WAL_CKPT_LOCK byte.
  1109   1108     ** If successful, the same bytes that are locked here are unlocked before
  1110   1109     ** this function returns.
  1111   1110     */
  1112   1111     assert( pWal->ckptLock==1 || pWal->ckptLock==0 );
  1113   1112     assert( WAL_ALL_BUT_WRITE==WAL_WRITE_LOCK+1 );
  1114   1113     assert( WAL_CKPT_LOCK==WAL_ALL_BUT_WRITE );
  1115   1114     assert( pWal->writeLock );
  1116   1115     iLock = WAL_ALL_BUT_WRITE + pWal->ckptLock;
  1117         -  nLock = SQLITE_SHM_NLOCK - iLock;
  1118         -  rc = walLockExclusive(pWal, iLock, nLock);
         1116  +  rc = walLockExclusive(pWal, iLock, WAL_READ_LOCK(0)-iLock);
         1117  +  if( rc==SQLITE_OK ){
         1118  +    rc = walLockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1);
         1119  +    if( rc!=SQLITE_OK ){
         1120  +      walUnlockExclusive(pWal, iLock, WAL_READ_LOCK(0)-iLock);
         1121  +    }
         1122  +  }
  1119   1123     if( rc ){
  1120   1124       return rc;
  1121   1125     }
         1126  +
  1122   1127     WALTRACE(("WAL%p: recovery begin...\n", pWal));
  1123   1128   
  1124   1129     memset(&pWal->hdr, 0, sizeof(WalIndexHdr));
  1125   1130   
  1126   1131     rc = sqlite3OsFileSize(pWal->pWalFd, &nSize);
  1127   1132     if( rc!=SQLITE_OK ){
  1128   1133       goto recovery_error;
................................................................................
  1252   1257             pWal->hdr.mxFrame, pWal->zWalName
  1253   1258         );
  1254   1259       }
  1255   1260     }
  1256   1261   
  1257   1262   recovery_error:
  1258   1263     WALTRACE(("WAL%p: recovery %s\n", pWal, rc ? "failed" : "ok"));
  1259         -  walUnlockExclusive(pWal, iLock, nLock);
         1264  +  walUnlockExclusive(pWal, iLock, WAL_READ_LOCK(0)-iLock);
         1265  +  walUnlockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1);
  1260   1266     return rc;
  1261   1267   }
  1262   1268   
  1263   1269   /*
  1264   1270   ** Close an open wal-index.
  1265   1271   */
  1266   1272   static void walIndexClose(Wal *pWal, int isDelete){

Changes to test/walro2.test.

    77     77       code3 { sqlite3 db3 test.db2 }
    78     78       sql3 { SELECT * FROM t1 }
    79     79     } {a b c d}
    80     80   
    81     81     do_test 1.3.2 {
    82     82       sql1 { SELECT * FROM t1 }
    83     83     } {a b c d}
           84  +
           85  +  code1 { db close  }
           86  +  code2 { db2 close }
           87  +  code3 { db3 close }
           88  +
           89  +  do_test 2.1 {
           90  +    code2 { sqlite3 db2 test.db }
           91  +    sql2 { 
           92  +      INSERT INTO t1 VALUES('e', 'f');
           93  +      INSERT INTO t1 VALUES('g', 'h');
           94  +    }
           95  +    file exists test.db-shm
           96  +  } {1}
           97  +
           98  +  do_test 2.2 {
           99  +    forcecopy test.db test.db2
          100  +    forcecopy test.db-wal test.db2-wal
          101  +    forcecopy test.db-shm test.db2-shm
          102  +    code1 {
          103  +      sqlite3 db file:test.db2?readonly_shm=1
          104  +    }
          105  +    sql1 { 
          106  +      BEGIN;
          107  +      SELECT * FROM t1;
          108  +    }
          109  +  } {a b c d}
          110  +
          111  +  do_test 2.3.1 {
          112  +    code3 { sqlite3 db3 test.db2 }
          113  +    sql3 { SELECT * FROM t1 }
          114  +  } {a b c d e f g h}
    84    115   
    85    116   }
    86    117   
    87    118   finish_test