【问题标题】:Deleting large sqlite table删除大型 sqlite 表
【发布时间】:2017-07-27 04:44:31
【问题描述】:

我陷入了独特的境地。在我的应用程序中,我有本地数据库。不知何故,其中一张表充满了垃圾数据,数据库变得非常庞大。到我知道时,大小已超过 1 GB。因此,我不断收到数据库锁定异常,因为读取该表上的垃圾行非常慢。调试后,我知道它是哪个表,现在我想删除它(删除整个表或删除所有行)但是每当我对该表执行任何操作时,数据库都会被锁定并发生 ANR。所以我不知道如何摆脱那张桌子。我无法卸载应用程序。

请注意,我在我的 Android 应用中使用 GreenDao。

我已经尝试过以下事情

1) DROP TABLE mytable;
2) DELETE FROM mytable;
3) DaoSession.getMyDao().deleteAll(); // this is a greedao method but it internally performs 2nd query I mentioned I think

在所有情况下。它只是产生 ANR。并且应用程序数据库被锁定。

编辑:我也在单独的线程中尝试过,它只是避免了 ANR,但没有删除表并且数据库仍然被锁定。

锁定后,每当其他线程尝试写入 db 时,我都会得到这个,这是显而易见的。

E/SQLiteDatabase: Failed to open database '/data/user/0/myapp/databases/mydb.db'.
 android.database.sqlite.SQLiteDatabaseLockedException: database is locked (code 5): , while compiling: PRAGMA journal_mode
 #################################################################
 Error Code : 5 (SQLITE_BUSY)
 Caused By : The database file is locked.
 (database is locked (code 5): , while compiling: PRAGMA journal_mode)
 #################################################################
 at android.database.sqlite.SQLiteConnection.nativePrepareStatement(Native Method)
 at android.database.sqlite.SQLiteConnection.acquirePreparedStatement(SQLiteConnection.java:1000)
 at android.database.sqlite.SQLiteConnection.executeForString(SQLiteConnection.java:704)
 at android.database.sqlite.SQLiteConnection.setJournalMode(SQLiteConnection.java:385)
 at android.database.sqlite.SQLiteConnection.setWalModeFromConfiguration(SQLiteConnection.java:359)
 at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:248)
 at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:199)
 at android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:514)
 at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:206)
 at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:178)
 at android.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:934)
 at android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:895)
 at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:708)
 at android.app.ContextImpl.openOrCreateDatabase(ContextImpl.java:646)
 at android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java:283)
 at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:223)
 at android.database.sqlite.SQLiteOpenHelper.getReadableDatabase(SQLiteOpenHelper.java:187)
 at com.intouchapp.database.IntouchDb.getNewReadableDaoSesssion(IntouchDb.java:80)
 at com.intouchapp.models.ActivityLogsDb.getCursorOfAllResults(ActivityLogsDb.java:298)
 at com.intouchapp.services.ActivityLogsDbInsertionService.onHandleIntent(ActivityLogsDbInsertionService.java:73)
 at android.app.IntentService$ServiceHandler.handleMessage(IntentService.java:66)
 at android.os.Handler.dispatchMessage(Handler.java:102)
 at android.os.Looper.loop(Looper.java:148)
 at android.os.HandlerThread.run(HandlerThread.java:61)

我也明白了,

The connection pool for database '+data+user+0+myapp+databases+mydb' has been unable to grant a connection to thread 2262 (SyncAdapterThread-1) with flags 0x2 for 12.0060005 seconds.
Connections: 1 active, 0 idle, 0 available.

Requests in progress:
executeForChangedRowCount started 12645ms ago - running, sql="DELETE FROM 'mytable'"

这清楚地表明它无法执行 "DELETE FROM 'mytable'" 这个特定的查询因此锁定。

【问题讨论】:

  • 当您在 主 UI 线程中执行长时间的耗时操作时会发生 ANR,因此为了避免 ANR,您必须在后台执行此操作
  • 是的,我也在单独的线程中尝试过。但它只是避免了 ANR。删除表不走运。
  • 那么堆栈跟踪是什么?
  • 我觉得这个post和你的问题有关

标签: android sqlite android-sqlite greendao greendao-generator


【解决方案1】:

SQLite 用于写操作时会锁定数据库。 您应该注意与此有关的一些要点:-

  • DataBase 操作应该在另一个线程中使用,而不是在 UI 线程中。
  • 创建 SQLiteOpenHelper 类的单个实例
  • 完成任务后关闭所有数据库实例
  • 始终使用 endTransaction()
  • 关闭 finally 块中的所有数据库实例

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-08-21
    • 1970-01-01
    • 1970-01-01
    • 2018-10-16
    • 2023-03-14
    • 1970-01-01
    • 2014-09-06
    • 1970-01-01
    相关资源
    最近更新 更多