Удаление большой таблицы 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'"
этот конкретный запрос, следовательно, блокировка.
1 ответ
SQLite блокирует базу данных, когда она используется для операции записи. Вы должны позаботиться о некоторых моментах относительно этого:
- Операция базы данных должна использоваться в другом потоке, а не в потоке пользовательского интерфейса.
- Сделайте один экземпляр класса SQLiteOpenHelper
- закрыть все экземпляры базы данных после завершения задачи
- всегда используйте endTransaction()
- закрыть весь экземпляр базы данных в блоке finally