En primer lugar, algunos antecedentes:Mejor detección de la corrupción SQLite
Mi Android aplicación tiene mesa de DB con una gran cantidad de filas de cuatro columnas. Envía solicitudes al servidor y el servidor responde solo cuando todos estos cuatro valores son "válidos". Algunos de los miles de usuarios informaron que algo no funciona para ellos (ya que no están obteniendo los resultados del servidor) - Intenté descubrir qué causaba el problema y resultó que la única causa posible es la Daño de DB que no se detecta.
En los registros de ACRA recibo algunos mensajes con errores de SQL, pero se trata de que la aplicación no puede abrir el archivo porque está dañado. Eso me dio alguna pista, pero todavía no estaba convencido de que este fuera el problema. Por lo tanto, he creado un script de Python muy sencillo que cambia bytes aleatorios en el archivo de base de datos y los controles cómo SQLite se ocupará de que:
import random
import array
import sqlite3
db = array.array('B')
db.fromstring(open('db').read())
ta = [x for x in sqlite3.connect('db').execute('SELECT * FROM table ORDER BY _id')]
results = [0,0,0,0]
tries = 1000
for i in xrange(0,tries):
work = db[:]
while work == db:
for j in xrange(0,random.randint(1,5)):
work[random.randint(1,len(db))-1] = random.randint(0,255)
work.tofile(open('outdb','w'))
try:
c = sqlite3.connect('outdb')
results[0] += 1
for r in c.execute('PRAGMA integrity_check;'):
results[1] += 1 if (r[0] == 'ok') else 0
except:
continue
try:
results[3] += 1 if [x for x in c.execute('SELECT * FROM table ORDER BY _id')] != ta else 0
results[2] += 1
except:
c.close()
continue
print 'Results for '+str(tries)+' tests:'
print 'Creating connection failed '+str(tries-results[0])+ ' times'
print 'Integrity check failed '+str(results[0]-results[1])+ ' times'
print 'Running a SELECT * query failed '+str(results[1]-results[2])+ ' times'
print 'Data was succesfully altered '+str(results[3])+ ' times'
Los resultados mostraron que "la edición de" datos de la tabla de esta manera es muy posible:
Results for 1000 tests:
Creating connection failed 0 times
Integrity check failed 503 times
Running a SELECT * query failed 289 times
Data was succesfully altered 193 times
por lo general es interesante ver que la ejecución de una consulta falló por medio de las modificaciones que no fue detectado por el control de integridad, pero lo más interesante para mí es que algo puede cambiar bytes aleatorios en mi DB haciendo mi solicitud inútil para una parte de mis usuarios.
He leído sobre posibles causas de corrupción en el sitio web de SQLite y también en StackOverflow, sé que p. forzar el cierre de la aplicación puede dañar el DB. Me gustaría saber si es posible implementar una verificación de integridad de DB rápida y más sólida.
Estoy leyendo los datos de una columna de toda la tabla al inicio (para autocompletar), así que pensé en calcular algunos hash de todos los valores - Creo que esto funcionaría bastante bien, ya que algunas funciones hash son diseñado solo para hacer comprobaciones de integridad, pero tal vez haya una solución más simple, más rápida y mejor. Por lo tanto, se lo pregunto, si conoce alguno.
Como se sugiere en la respuesta a esta pregunta: http://stackoverflow.com/questions/11490250/does-sqlite-checksum-its-data Puede codificar sus datos utilizando la corrección de errores hacia adelante. Tal vez no sea más simple o más rápido (un hash parece una solución razonable y simple), pero quizás sea mejor. De hecho, tendrías la oportunidad de corregir errores, no solo de detectarlos. – bsa
Esta pregunta es un poco antigua, pero quería mencionar [esta respuesta] (http://stackoverflow.com/questions/12418600/how-do-you-determine-if-an-sqlite-or-sqback-is- corrupt-in-java) menciona 'PRAGMA quick_check;' que aparentemente hace algún tipo de escaneo * sobre los datos (?) *. Tengo curiosidad por saber qué tipo de resultados daría en el caso de prueba anterior, pero no estoy seguro de cómo lo integraría. ** EDITAR: [la documentación] (http://www.sqlite.org/pragma.html#pragma_integrity_check) dice 'quick_check' es una versión más rápida de' identity_check'. ** Ah. –