La base de datos SQLite de Android se corrompe
Este enlace describe mi problema exactamente: http://old.nabble.com/Android-database-corruption-td28044218.html#a28044218
Hay alrededor de 300 personas que utilizan mi aplicación para Android en este momento y de vez en cuando obtengo un informe de fallo en el servidor con este seguimiento de pila:
- Cómo evitar objetos duplicados en la base de datos DB4o
- Obtención de la excepción de base de datos de Sqlite en Android
- ¿Podemos usar una base de datos SQLITE aldready preparada para una aplicación phonegap?
- En java, ¿cómo puedo eliminar una tabla sqlite?
- Asegúrese de que SQLite en Android utiliza UTF-8 como un conjunto de caracteres
android.database.sqlite.SQLiteDatabaseCorruptException: database disk image is malformed at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2596) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2621) at android.app.ActivityThread.access$2200(ActivityThread.java:126) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1932) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:123) at android.app.ActivityThread.main(ActivityThread.java:4595) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:521) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618) at dalvik.system.NativeStart.main(Native Method) Caused by: android.database.sqlite.SQLiteDatabaseCorruptException: database disk image is malformed at android.database.sqlite.SQLiteQuery.native_fill_window(Native Method) at android.database.sqlite.SQLiteQuery.fillWindow(SQLiteQuery.java:75) at android.database.sqlite.SQLiteCursor.fillWindow(SQLiteCursor.java:295) at android.database.sqlite.SQLiteCursor.getCount(SQLiteCursor.java:276) at android.database.AbstractCursor.moveToPosition(AbstractCursor.java:171) at android.database.AbstractCursor.moveToFirst(AbstractCursor.java:248)
El resultado es la caída de la aplicación y la pérdida de todos los datos de la base de datos.
Una cosa a tener en cuenta es que cada vez que leo o escribo en la base de datos recibo una nueva SQLiteDatabase y la cierro tan pronto como termine. Hice esto en un intento de prevenir este tipo de errores de corrupción.
También intenté sincronizar todas las lecturas y escrituras del DB usando un solo objeto estático y eso no parecía ayudar.
¿Es posible que esto sea solo un error de SQLite?
Encontré un error similar con la aplicación de correo electrónico incorporada aquí: http://code.google.com/p/android/issues/detail?id=5610 .
Aquí está mi código:
public class KeyValueTableAdapter extends BaseTableAdapter { private String tableName; private String keyColumnName; private String valueColumnName; public KeyValueTableAdapter(Context context, String tableName, String keyColumnName, String valueColumnName) { super(context); this.tableName = tableName; this.keyColumnName = keyColumnName; this.valueColumnName = valueColumnName; } protected String getStringValue(int key) { Cursor cursor = null; SQLiteDatabase db = null; String value; try { db = dbOpenHelper.getReadableDatabase(); cursor = db.query(true, tableName, new String[] { valueColumnName }, keyColumnName + "=" + key, null, null, null, null, null); if ((cursor.getCount() == 0) || !cursor.moveToFirst()) { value = null; } else { value = cursor.getString(0); } } finally { if (cursor != null) cursor.close(); if (db != null) db.close(); dbOpenHelper.close(); } return value; } } public abstract class BaseTableAdapter { protected DbOpenHelper dbOpenHelper; public BaseTableAdapter(Context context) { this.dbOpenHelper = new DbOpenHelper(context, DatabaseSettings.DATABASE_NAME, null, DatabaseSettings.DATABASE_VERSION); } }
- ¿Tengo que usar _ID como una clave primaria de SQlite? Y tiene que ser un INT? (Android Dev)
- Limitar el número de filas devueltas desde sqlite
- Android Seleccionar fila por Id en Sqlite?
- No hay tal tabla android_metadata, ¿cuál es el problema?
- No se puede usar como cláusula en la aplicación android
- Actualizar la base de datos sqlite que copio de la carpeta de activos (Android)
- ¿Cómo crear una vista sql (CREATE VIEW) en sqlite (android) y consulta?
- ¿Cómo acceder a la base de datos cuando se desarrolla en el teléfono Android?
"El DB mantiene la información de sesión por lo que no es muy factible hacer una copia de seguridad.Los datos cambian por minuto"
Debe intentar usar SharedPreferences: almacena pares clave-valor (en el fondo, utiliza un archivo). Almacenamiento de valores:
SharedPreferences sp=MyActivity.getSharedPreferences("Name", Context.MODE_PRIVATE); SharedPreferences.Editor editor = sp.edit(); editor.putString("key", value); editor.putBoolean("another", true); editor.commit();
Recuperando datos:
sp.getString("key", "Not found"); // "Not found" is the default value // if sp does not contain the specified key sp.getBoolean("another", false); // false is the default value // if sp does not contain the specified key
Vea getSharedPreferences y SharedPreferences para una descripción más detallada.
Lo más probable es que el proceso de la base de datos se esté matando durante una E / S. Por ejemplo, por un asesino de tareas, o si está permitiendo que las operaciones de escritura de db continúen durante un tiempo cuando la aplicación debe apagar o dormir …
Vea si puede reproducir el problema poniendo su aplicación en un bucle de escritura de DB y usando un asesino de tareas en él.
Escenario: 32 bytes que se escriben en la base de datos, la tarea de escritor se pierde después de sólo escribir 10, resultado: base de datos izquierda en estado inconsistente y posiblemente corrupto.
Véase también: Android proceso asesino
EDIT: abrir y cerrar el DB para cada lectura / escritura? ¡Para! 🙂
El uso de varias instancias de SQLiteDatabase
podría estar causando el problema si tiene dos instancias que actualizan el mismo archivo de base de datos al mismo tiempo.
Implementar un proceso de backup db cada día, y si el DB se corrompe basta con reemplazar la base de datos con una copia de seguridad. Puede utilizar métodos simples de copia de copia de archivos para mantener una copia de seguridad cada día.
Ya que no puedo comentar -yet- en el post de Brad.
Tengo que estar de acuerdo con la sobrecarga adicional.
Tengo un HTC Magic como mi teléfono diario, y el carnero siempre es un problema.
Los teléfonos con Android están en extremos muy diferentes del $$$
Algunos son super baratos y algunos son muy caros, esto básicamente se reduce a la RAM, y la CPU.
Las personas que ejecutan asesinos de tareas arruinan sus teléfonos Android.
Como desarrollador, debe sugerir a la gente que no los use, o simplemente negar el apoyo a las personas que utilizan asesinos de tareas, ya que android no necesita estas "mejoras" (pregunte a steve (cianógeno))
También la new
declaración en android es muy costosa.
Desea limitar la cantidad de llamadas new
al programar para android.
La programación para android es todo sobre la reutilización de la memoria preciosa. (HTC Magics / Dreams sólo tiene 96 MB disponibles para las aplicaciones, y la mayor parte ya está en uso)
En cuanto a su SQLiteDB … la API dice que su SQLiteDB es privado para su aplicación.
No veo por qué necesita abrir y cerrar una conexión NUEVA cada vez que quiera leer o escribir en ella.
Prefiero mantener la conexión abierta hasta que el usuario pierda el foco de ella.
Sin embargo, si está escribiendo un proveedor de contenido, esa es una historia diferente.