code: func (kv *keyValue) finalize() error {
  	if err := createTables(kv.db, kv.database); err != nil {
  		return err
  	}
  
  	if err := kv.ping(); err != nil {
  		return fmt.Errorf("MySQL db unreachable: %v", err)
  	}
  
  	version, err := kv.SchemaVersion()
  	if err != nil {
  		return fmt.Errorf("error getting current database schema version: %v", err)
  	}
  	if version == 0 {
  		// Newly created table case
  		if _, err := kv.db.Exec(fmt.Sprintf(`REPLACE INTO %s.meta VALUES ('version', ?)`, kv.database), requiredSchemaVersion); err != nil {
  			return fmt.Errorf("error setting schema version: %v", err)
  		}
  		return nil
  	}
  	if version != requiredSchemaVersion {
  		if version == 20 && requiredSchemaVersion == 21 {
  			fmt.Fprintf(os.Stderr, fixSchema20to21)
  		}
  		if env.IsDev() {
  			// Good signal that we're using the devcam server, so help out
  			// the user with a more useful tip:
  			return sorted.NeedWipeError{
  				Msg: fmt.Sprintf("database schema version is %d; expect %d (run \"devcam server --wipe\" to wipe both your blobs and re-populate the database schema)", version, requiredSchemaVersion),
  			}
  		}
  		return sorted.NeedWipeError{
  			Msg: fmt.Sprintf("database schema version is %d; expect %d (need to re-init/upgrade database?)",
  				version, requiredSchemaVersion),
  		}
  	}
  
  	return nil
  }
docs: // finalize should be called on a keyValue initialized with newKVDB.