How to manually perform checkpoint in SQLite andro

2020-07-18 10:01发布

I'm trying to create a backup of my sqlite database and I want to flush the content of the WAL file in the db first.

Here is my SQLiteOpenHelper:

public class MyDBHelper extends SQLiteOpenHelper {

private Context mContext;
private static MyDBHelper mInstance = null;

private MyDBHelper(final Context context, String databaseName) {
    super(new MYDB(context), databaseName, null, DATABASE_VERSION);
    this.mContext = context;
}

@Override
public void onCreate(SQLiteDatabase db) {

}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

}
   public static MyDBHelper getInstance(Context context) {

    if (mInstance == null) {
        mInstance = new MyDBHelper(context, DATABASE_NAME);
    }
    return mInstance;
}

  private void closeDataBase(Context context) {
    getInstance(context).close();
}

}

Now, my understanding is that after a checkpoint is completed, the mydb.db-wal file should be empty. Is that correct?

Here is what I've tried so far: 1.

    public Completable flushWalInDB() {
    return Completable.fromAction(new Action() {
        @Override
        public void run() throws Exception {
            getInstance(mContext).getReadableDatabase().rawQuery("pragma wal_checkpoint;", null);
        }
    });
}

This doesn't throw an error but doesn't seem to do anything. After running this, I physically checked my mydb.db-wal file and had the same size. I also checked the db on the device and nothing was added in the database

After some digging around I found this [https://stackoverflow.com/a/30278485/2610933][1] and tried this:

2.

    public Completable flushWalInDB() {
    return Completable.fromAction(new Action() {
        @Override
        public void run() throws Exception {
            getInstance(mContext).getReadableDatabase().execSQL("pragma wal_checkpoint;");
        }
    });
}

When running this it throws an error:

unknown error (code 0): Queries can be performed using SQLiteDatabase query or rawQuery methods only.

And based on this answer [https://stackoverflow.com/a/19574341/2610933][1] , I also tried to VACUUM the DB but nothing seems to happen.

 public Completable vacuumDb() {
    return Completable.fromAction(new Action() {
        @Override
        public void run() throws Exception {
            getInstance(mContext).getReadableDatabase().execSQL("VACUUM");
        }
    });
} 
}

Whats is the correct way of flushing the WAL file in the DB before creating a backup?

Thank you.

1条回答
【Aperson】
2楼-- · 2020-07-18 10:59

PRAGMA wal_checkpoint(2) does copy all data from the WAL into the actual database file, but it does not remove the -wal file, and any concurrent connections can make new changes right afterwards.

If you want to be really sure that there is no WAL to interfere with your backup, run PRAGMA journal_mode = DELETE. (You can switch it back afterwards.)

查看更多
登录 后发表回答