Android *.db-journal
View Code<!-- The default journal mode to use use when Write-Ahead Logging is not active. Choices are: OFF, DELETE, TRUNCATE, PERSIST and MEMORY. PERSIST may improve performance by reducing how often journal blocks are reallocated (compared to truncation) resulting in better data block locality and less churn of the storage media. --> <string name="db_default_journal_mode">PERSIST</string>
View Code /** * Gets the default journal mode when WAL is not in use. */ public static String getDefaultJournalMode() { return SystemProperties.get("debug.sqlite.journalmode", Resources.getSystem().getString( com.android.internal.R.string.db_default_journal_mode)); }
View Code... private void open() { mConnectionPtr = nativeOpen(mConfiguration.path, mConfiguration.openFlags, mConfiguration.label, SQLiteDebug.DEBUG_SQL_STATEMENTS, SQLiteDebug.DEBUG_SQL_TIME); setPageSize(); setForeignKeyModeFromConfiguration(); setWalModeFromConfiguration(); setJournalSizeLimit(); setAutoCheckpointInterval(); setLocaleFromConfiguration(); // Register custom functions. final int functionCount = mConfiguration.customFunctions.size(); for (int i = 0; i < functionCount; i++) { SQLiteCustomFunction function = mConfiguration.customFunctions.get(i); nativeRegisterCustomFunction(mConnectionPtr, function); } } ... private void setWalModeFromConfiguration() { if (!mConfiguration.isInMemoryDb() && !mIsReadOnlyConnection) { if ((mConfiguration.openFlags & SQLiteDatabase.ENABLE_WRITE_AHEAD_LOGGING) != 0) { setJournalMode("WAL"); setSyncMode(SQLiteGlobal.getWALSyncMode()); } else { setJournalMode(SQLiteGlobal.getDefaultJournalMode()); setSyncMode(SQLiteGlobal.getDefaultSyncMode()); } } } ... private void setJournalMode(String newValue) { String value = executeForString("PRAGMA journal_mode", null, null); if (!value.equalsIgnoreCase(newValue)) { try { String result = executeForString("PRAGMA journal_mode=" + newValue, null, null); if (result.equalsIgnoreCase(newValue)) { return; } // PRAGMA journal_mode silently fails and returns the original journal // mode in some cases if the journal mode could not be changed. } catch (SQLiteDatabaseLockedException ex) { // This error (SQLITE_BUSY) occurs if one connection has the database // open in WAL mode and another tries to change it to non-WAL. } // Because we always disable WAL mode when a database is first opened // (even if we intend to re-enable it), we can encounter problems if // there is another open connection to the database somewhere. // This can happen for a variety of reasons such as an application opening // the same database in multiple processes at the same time or if there is a // crashing content provider service that the ActivityManager has // removed from its registry but whose process hasn't quite died yet // by the time it is restarted in a new process. // // If we don't change the journal mode, nothing really bad happens. // In the worst case, an application that enables WAL might not actually // get it, although it can still use connection pooling. Log.w(TAG, "Could not change the database journal mode of '" + mConfiguration.label + "' from '" + value + "' to '" + newValue + "' because the database is locked. This usually means that " + "there are other open connections to the database which prevents " + "the database from enabling or disabling write-ahead logging mode. " + "Proceeding without changing the journal mode."); } } ... /** * Executes a statement that returns a single {@link String} result. * * @param sql The SQL statement to execute. * @param bindArgs The arguments to bind, or null if none. * @param cancellationSignal A signal to cancel the operation in progress, or null if none. * @return The value of the first column in the first row of the result set * as a <code>String</code>, or null if none. * * @throws SQLiteException if an error occurs, such as a syntax error * or invalid number of bind arguments. * @throws OperationCanceledException if the operation was canceled. */ public String executeForString(String sql, Object[] bindArgs, CancellationSignal cancellationSignal) { if (sql == null) { throw new IllegalArgumentException("sql must not be null."); } final int cookie = mRecentOperations.beginOperation("executeForString", sql, bindArgs); try { final PreparedStatement statement = acquirePreparedStatement(sql); try { throwIfStatementForbidden(statement); bindArguments(statement, bindArgs); applyBlockGuardPolicy(statement); attachCancellationSignal(cancellationSignal); try { return nativeExecuteForString(mConnectionPtr, statement.mStatementPtr); } finally { detachCancellationSignal(cancellationSignal); } } finally { releasePreparedStatement(statement); } } catch (RuntimeException ex) { mRecentOperations.failOperation(cookie, ex); throw ex; } finally { mRecentOperations.endOperation(cookie); } }
Sqlite从3.7.0版本开始引入了WAL,这是一种新的事务回滚机制。
Android第一次操作数据库时,*.db-journal文件会被自动创建,且是持久保存在磁盘中,如果没有操作异常或者不需要事务回滚时,此文件的大小为0。这种机制避免了每次生成和删除*.db-journal文件的开销。