System.err: android.database.sqlite.SQLiteCantOpenDatabaseException: unable to open database file (c

12-08 15:10:17.278 30336 30351 E SQLiteLog: (14) cannot open file at line 31289 of [5a3022e081]
12-08 15:10:17.278 30336 30351 E SQLiteLog: (14) os_unix.c:31289: (2) open(/data/user/0/com.xxx.xxxx/k.db-wal) -  
12-08 15:10:17.278 30336 30351 E SQLiteLog: (14) unable to open database file
12-08 15:10:17.278 30336 30351 W System.err: android.database.sqlite.SQLiteCantOpenDatabaseException: unable to open database file (code 14): , while compiling: select * from content
12-08 15:10:17.279 30336 30351 W System.err:     at android.database.sqlite.SQLiteConnection.nativePrepareStatement(Native Method)
12-08 15:10:17.279 30336 30351 W System.err:     at android.database.sqlite.SQLiteConnection.acquirePreparedStatement(SQLiteConnection.java:926)
12-08 15:10:17.279 30336 30351 W System.err:     at android.database.sqlite.SQLiteConnection.prepare(SQLiteConnection.java:537)
12-08 15:10:17.279 30336 30351 W System.err:     at android.database.sqlite.SQLiteSession.prepare(SQLiteSession.java:588)
12-08 15:10:17.279 30336 30351 W System.err:     at android.database.sqlite.SQLiteProgram.<init>(SQLiteProgram.java:58)
12-08 15:10:17.279 30336 30351 W System.err:     at android.database.sqlite.SQLiteQuery.<init>(SQLiteQuery.java:37)
12-08 15:10:17.279 30336 30351 W System.err:     at android.database.sqlite.SQLiteDirectCursorDriver.query(SQLiteDirectCursorDriver.java:44)
12-08 15:10:17.279 30336 30351 W System.err:     at android.database.sqlite.SQLiteDatabase.rawQueryWithFactory(SQLiteDatabase.java:1316)
12-08 15:10:17.279 30336 30351 W System.err:     at android.database.sqlite.SQLiteDatabase.rawQuery(SQLiteDatabase.java:1255)

12-08 15:10:17.279 30336 30351 W System.err:     at com.uusafe.wrapper.model.KHelper.load(KHelper.java:417) 


sqlite是支持write ahead logging(WAL)模式的,开启WAL模式可以提高写入数据库的速度,读和写之间不会阻塞,但是写与写之间依然是阻塞的,但是如果使用默认的TRUNCATE模式,当写入数据时会阻塞android中其他线程或者进程的读操作,并发降低。 相反,使用WAL可以提高并发。 由于使用WAL比ROLLBACK JOURNAL的模式减少了写的I/O,所以写入时速度较快,但是由于在读取数据时也需要读取WAL日志验证数据的正确性,所以读取数据相对要慢。当开启了WAL模式更新数据时,会先将数据写入到*.db-wal文件中,而不是直接修改数据库文件,当执行checkpoint时或某个时间点才会将数据更新到数据库文件。当出现rollback也只是清除wal日志文件,而ROLLBACK JOURNAL模式,当数据有更新时,先将需要修改的数据备份到journal文件中,然后修改数据库文件,当发生rollback,从journal日志中取出数据,并修改数据库文件,然后清除journal日志。 从以上流程来看 WAL在数据更新上I/0量要小,所以写操作要快。


有些人认为网上有有效的简单解决办法直接删除,

String book_journal = "/data/data/com.stevenhu.android.phone.ui/databases/Book.db-journal";
File file_journal = new File(book_journal);
if ( file_journal.exists() )
{
file_journal.delete();
}


为什么会报错呢, 原因是手机默认开启了wal 模式, 但是我们读取的db 文件及其目录不可写, 导致,系统在进行数据库的wal 操作,打开k.db-wal 文件时, 该临时文件不能创建, 导致 执行的事物操作中断。


  1. public boolean enableWriteAheadLogging() {  
  2.         // make sure the database is not READONLY. WAL doesn't make sense for readonly-databases.  
  3.         if (isReadOnly()) {  
  4.             return false;  
  5.         }  
  6.         // acquire lock - no that no other thread is enabling WAL at the same time  
  7.         lock();  
  8.         try {  
  9.             if (mConnectionPool != null) {  
  10.                 // already enabled  
  11.                 return true;  
  12.             }  
  13.             if (mPath.equalsIgnoreCase(MEMORY_DB_PATH)) {  
  14.                 Log.i(TAG, "can't enable WAL for memory databases.");  
  15.                 return false;  
  16.             }  
  17.   
  18.             // make sure this database has NO attached databases because sqlite's write-ahead-logging  
  19.             // doesn't work for databases with attached databases  
  20.             if (mHasAttachedDbs) {  
  21.                 if (Log.isLoggable(TAG, Log.DEBUG)) {  
  22.                     Log.d(TAG,  
  23.                             "this database: " + mPath + " has attached databases. can't  enable WAL.");  
  24.                 }  
  25.                 return false;  
  26.             }  
  27.             mConnectionPool = new DatabaseConnectionPool(this);  
  28.             setJournalMode(mPath, "WAL");  
  29.             return true;  
  30.         } finally {  
  31.             unlock();  
  32.         }  
  33.     } 

/**
 * Open flag: Flag for {@link #openDatabase} to open the database file with
 * write-ahead logging enabled by default.  Using this flag is more efficient
 * than calling {@link #enableWriteAheadLogging}.
 *
 * Write-ahead logging cannot be used with read-only databases so the value of
 * this flag is ignored if the database is opened read-only.
 *
 * @see #enableWriteAheadLogging
 */
public static final int ENABLE_WRITE_AHEAD_LOGGING = 0x20000000;

这些源码都说明了一个问题, 开启wal 模式需要对db 文件所在的目录可写权限。

File export = new File(path, PathHelper.EXPORT_DIR);
Log.e("tianxuhong", "dir"+export.getAbsolutePath());
export.setWritable(true, false);

// for app sql load flags  to readOnly
public static final int SQL_FLAGS_READONLY = SQLiteDatabase.NO_LOCALIZED_COLLATORS|SQLiteDatabase.CONFLICT_IGNORE|SQLiteDatabase.OPEN_READONLY;

db = SQLiteDatabase.openDatabase(a, null, UGlobal.SQL_FLAGS_READONLY);




  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值