【发布时间】:2016-05-07 13:32:42
【问题描述】:
所以在极少数情况下,我会看到“尝试写入只读数据库”消息,但我无法弄清楚问题出在哪里。我将从我的 logcat 中的堆栈跟踪开始......正如您从时间戳中看到的那样,我在尝试写入前仅 1 毫秒检查 db.isReadOnly()。 (isOpen=true, readOnly=false)
01-29 13:47:49.115: D/AWT(11055): #479.Got writable database (230537815): isOpen: (true) isReadOnly: (false) inTransaction: (false)
01-29 13:47:49.116: D/AWT(11055): #479.in transaction: Got writable database (230537815): isOpen: (true) isReadOnly: (false) inTransaction: (true)
01-29 13:47:49.116: E/SQLiteLog(11055): (1032) statement aborts at 15: [INSERT INTO Events(col1,col2,col3,col4) VALUES (?,?,?,?)]
01-29 13:47:49.117: E/SQLiteDatabase(11055): Error inserting data="scrubbed"
01-29 13:47:49.117: E/SQLiteDatabase(11055): android.database.sqlite.SQLiteReadOnlyDatabaseException: attempt to write a readonly database (code 1032)
01-29 13:47:49.117: E/SQLiteDatabase(11055): at android.database.sqlite.SQLiteConnection.nativeExecuteForLastInsertedRowId(Native Method)
01-29 13:47:49.117: E/SQLiteDatabase(11055): at android.database.sqlite.SQLiteConnection.executeForLastInsertedRowId(SQLiteConnection.java:780)
01-29 13:47:49.117: E/SQLiteDatabase(11055): at android.database.sqlite.SQLiteSession.executeForLastInsertedRowId(SQLiteSession.java:788)
01-29 13:47:49.117: E/SQLiteDatabase(11055): at android.database.sqlite.SQLiteStatement.executeInsert(SQLiteStatement.java:86)
01-29 13:47:49.117: E/SQLiteDatabase(11055): at android.database.sqlite.SQLiteDatabase.insertWithOnConflict(SQLiteDatabase.java:1471)
01-29 13:47:49.117: E/SQLiteDatabase(11055): at android.database.sqlite.SQLiteDatabase.insert(SQLiteDatabase.java:1341)
01-29 13:47:49.117: E/SQLiteDatabase(11055): at com.company.DbHelper.insertBatch(EventsDbHelper.java:174)
01-29 13:47:49.117: D/AWT(11055): #479.finalizing transaction: Got writable database (230537815): isOpen: (true) isReadOnly: (false) inTransaction: (true)
01-29 13:47:49.118: W/SQLiteLog(12120): (28) file unlinked while open: /data/user/0/com.company.app/databases/MyDatabase.db
来自我的来源:
public void insertBatch(LinkedList<WriteQueue.DatabaseRecord> writeQueue) throws Exception {
Log.d("AWT", "EventsDbHelper->insertBatch()");
if (writeQueue == null) {
return;
}
Iterator<DatabaseRecord> it = writeQueue.iterator();
SQLiteDatabase db = this.getWritableDatabase();
Log.d("AWT", String.format("Got writable database (%s): isOpen: (%s) isReadOnly: (%s) inTransaction: (%s)",
db.hashCode(), db.isOpen(), db.isReadOnly(), db.inTransaction()));
try {
db.beginTransaction();
while (it.hasNext()) {
DatabaseRecord record = it.next();
ContentValues initialValues = new ContentValues();
initialValues.put(col1, val1);
initialValues.put(col2, val2);
initialValues.put(col3, val3);
initialValues.put(col4, val4);
Log.d("AWT", String.format("in transaction: Got writable database (%s): isOpen: (%s) isReadOnly: (%s) inTransaction: (%s)",
db.hashCode(), db.isOpen(), db.isReadOnly(), db.inTransaction()));
db.insert(DBTBL, null, initialValues);
}
Log.d("AWT", String.format("finalizing transaction: Got writable database (%s): isOpen: (%s) isReadOnly: (%s) inTransaction: (%s)",
db.hashCode(), db.isOpen(), db.isReadOnly(), db.inTransaction()));
db.setTransactionSuccessful();
} catch (Exception e) {
Log.e(TAG, "Error inserting batch record into database.", e);
} finally {
try {
db.endTransaction();
db.close();
} catch (Exception e) {
Log.e(TAG, Global.DB_ERROR, e);
}
}
}
所以我认为可能发生了两件事之一。
- 在检查和尝试批量插入之间的 1 毫秒内,数据库确实被关闭/设置为“只读”。
- isReadOnly 在骗我,没有准确报告数据库的状态。
- 数据库在我的插入过程中被删除了!请参阅上面日志的最后一行。我为 SQLite 打开了严格的日志记录并注意到了上述情况。我怀疑第三方库可能会删除我的所有数据库。
虽然目前没有想法,但我愿意尝试任何建议。
【问题讨论】:
-
在批量插入完成后,在 dbHelper 类的其他地方完成关闭。我也取消了所有关闭呼叫,但这对这种行为没有任何影响。
-
也添加了(参见更新的代码和 logcat)。没有任何区别。
-
我会尝试一个完全干净的项目,只要有足够的支持就可以插入数据库。这将有助于隔离问题。我还尝试设置一个标志,以便该呼叫一次只允许一个呼叫。您可能会在第一个事件完成之前开始第二个事件。
-
我也遇到了类似类型的异常,并且严重坚持了下来。您找到任何解决方案还是找到原因?
标签: android sqlite android-sqlite