Additional schema mutex checks for sqlite3RootPageMoved().
Reduce the scope of sqlite3ResetInternalSchema() in a few places.

FossilOrigin-Name: 39c00907833413c0d97d3e06fdda967b825d23ea
diff --git a/src/build.c b/src/build.c
index 51b7905..7e73b6a 100644
--- a/src/build.c
+++ b/src/build.c
@@ -1866,10 +1866,13 @@
 ** in order to be certain that we got the right one.
 */
 #ifndef SQLITE_OMIT_AUTOVACUUM
-void sqlite3RootPageMoved(Db *pDb, int iFrom, int iTo){
+void sqlite3RootPageMoved(sqlite3 *db, int iDb, int iFrom, int iTo){
   HashElem *pElem;
   Hash *pHash;
+  Db *pDb;
 
+  assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
+  pDb = &db->aDb[iDb];
   pHash = &pDb->pSchema->tblHash;
   for(pElem=sqliteHashFirst(pHash); pElem; pElem=sqliteHashNext(pElem)){
     Table *pTab = sqliteHashData(pElem);
diff --git a/src/prepare.c b/src/prepare.c
index aad2bc0..b5edaf5 100644
--- a/src/prepare.c
+++ b/src/prepare.c
@@ -472,6 +472,7 @@
     sqlite3BtreeGetMeta(pBt, BTREE_SCHEMA_VERSION, (u32 *)&cookie);
     assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
     if( cookie!=db->aDb[iDb].pSchema->schema_cookie ){
+      sqlite3ResetInternalSchema(db, iDb);
       pParse->rc = SQLITE_SCHEMA;
     }
 
@@ -613,9 +614,6 @@
   if( pParse->checkSchema ){
     schemaIsValid(pParse);
   }
-  if( pParse->rc==SQLITE_SCHEMA ){
-    sqlite3ResetInternalSchema(db, -1);
-  }
   if( db->mallocFailed ){
     pParse->rc = SQLITE_NOMEM;
   }
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index 1d8194a..b874c5e 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -2956,7 +2956,7 @@
 extern int sqlite3PendingByte;
 #endif
 #endif
-void sqlite3RootPageMoved(Db*, int, int);
+void sqlite3RootPageMoved(sqlite3*, int, int, int);
 void sqlite3Reindex(Parse*, Token*, Token*);
 void sqlite3AlterFunctions(void);
 void sqlite3AlterRenameTable(Parse*, SrcList*, Token*);
diff --git a/src/vdbe.c b/src/vdbe.c
index 6dc305d..94fd0ff 100644
--- a/src/vdbe.c
+++ b/src/vdbe.c
@@ -551,7 +551,7 @@
   Op *pOp;                   /* Current operation */
   int rc = SQLITE_OK;        /* Value to return */
   sqlite3 *db = p->db;       /* The database */
-  u8 resetSchemaOnFault = 0; /* Reset schema after an error if true */
+  u8 resetSchemaOnFault = 0; /* Reset schema after an error if positive */
   u8 encoding = ENC(db);     /* The database encoding */
 #ifndef SQLITE_OMIT_PROGRESS_CALLBACK
   int checkProgress;         /* True if progress callbacks are enabled */
@@ -2953,7 +2953,6 @@
     */
     if( db->aDb[pOp->p1].pSchema->schema_cookie!=iMeta ){
       sqlite3ResetInternalSchema(db, pOp->p1);
-      sqlite3VdbeMutexResync(p);
     }
 
     p->expired = 1;
@@ -4534,8 +4533,10 @@
     pOut->u.i = iMoved;
 #ifndef SQLITE_OMIT_AUTOVACUUM
     if( rc==SQLITE_OK && iMoved!=0 ){
-      sqlite3RootPageMoved(&db->aDb[iDb], iMoved, pOp->p1);
-      resetSchemaOnFault = 1;
+      sqlite3RootPageMoved(db, iDb, iMoved, pOp->p1);
+      /* All OP_Destroy operations occur on the same btree */
+      assert( resetSchemaOnFault==0 || resetSchemaOnFault==iDb+1 );
+      resetSchemaOnFault = iDb+1;
     }
 #endif
   }
@@ -5969,9 +5970,8 @@
   sqlite3VdbeHalt(p);
   if( rc==SQLITE_IOERR_NOMEM ) db->mallocFailed = 1;
   rc = SQLITE_ERROR;
-  if( resetSchemaOnFault ){
-    sqlite3ResetInternalSchema(db, 0);
-    sqlite3VdbeMutexResync(p);
+  if( resetSchemaOnFault>0 ){
+    sqlite3ResetInternalSchema(db, resetSchemaOnFault-1);
   }
 
   /* This is the only way out of this procedure.  We have to