Удаление большой таблицы sqlite

Я застрял в уникальной ситуации. В моем приложении у меня есть локальная база данных. Каким-то образом одна из таблиц была заполнена ненужными данными, и база данных стала очень большой. К тому времени, когда я узнал, размер был более 1 ГБ. Поэтому я продолжал получать исключение блокировки базы данных, так как чтение ненужных строк в этой таблице было очень медленным. После отладки я выяснил, какая это таблица, и теперь я хочу ее удалить (либо удалить всю таблицу, либо удалить все строки), но всякий раз, когда я выполняю какую-либо операцию с этой таблицей, база данных блокируется и происходит ANR. Так что я не уверен, как избавиться от этой таблицы. Я не могу удалить приложение.

Обратите внимание, что я использую GreenDao в своем приложении для Android.

Я пробовал следующие вещи

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, но не удалял таблицу, а база данных все еще была заблокирована.

После блокировки я получаю это всякий раз, когда другой поток пытается записать в БД, что очевидно.

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'" этот конкретный запрос, следовательно, блокировка.


person Apr444    schedule 27.07.2017    source источник
comment
ANR возникает, когда вы выполняете длительную операцию в основном потоке пользовательского интерфейса, поэтому, чтобы избежать ANR, вы должны делать это в фоновом режиме.   -  person pskink    schedule 27.07.2017
comment
Да, я тоже пробовал в отдельной теме. но он просто избегал ANR. не повезло с удалением таблицы.   -  person Apr444    schedule 27.07.2017
comment
так какой была трассировка стека?   -  person pskink    schedule 27.07.2017
comment
Я думаю, что этот пост связан с вашей проблемой   -  person user456    schedule 27.07.2017
comment
Возможный дубликат Удаление строк в таблице вызывает БЛОКИРОВКИ   -  person ELITE    schedule 27.07.2017
comment
Как насчет создания аналогичной БД, а затем копирования данных из других таблиц, а затем переименования файлов БД, чтобы заменить большую таблицу? Предполагая, что проблема заключается только в доступе к большой таблице.   -  person MikeT    schedule 27.07.2017
comment
@MikeT Звучит как хорошая идея, но тогда размер этой огромной таблицы (более ГБ) будет складываться в общий размер приложения, даже если мы не используем эту базу данных. Что-то, что я не могу себе позволить.   -  person Apr444    schedule 27.07.2017
comment
@Apr444, извините, после замены на тестирование и т. Д., Удалите его (файл).   -  person MikeT    schedule 27.07.2017


Ответы (1)


SQLite блокирует базу данных, когда она используется для операции записи. Вы должны позаботиться о некоторых моментах относительно этого: -

  • Операция базы данных должна использоваться в другом потоке, а не в потоке пользовательского интерфейса.
  • Сделать один экземпляр класса SQLiteOpenHelper
  • закрыть все экземпляры базы данных после завершения задачи
  • всегда используйте endTransaction()
  • закрыть все экземпляры базы данных в блоке finally
person Alok Mishra    schedule 28.07.2017