Сначала немного фона:
В моем Android приложении есть таблица БД с большим количеством строк из четырех столбцов.Он отправляет запросы на сервер, а сервер отвечает только тогда, когда все эти четыре значения являются «действительными».Несколько тысяч пользователей сообщили, что у них что-то не работает (так как какое-то время они не получают результаты с сервера) - я пытался выяснить, что является причиной проблемы, и оказалось, что единственно возможная причина - этоПовреждение БД, которое не обнаружено.
В журналах ACRA я получил несколько сообщений с ошибками SQL, но они касались того, что приложение не может открыть файл из-за его повреждения.Это дало мне некоторую подсказку, но я все еще не был уверен, что это проблема.Итак, я создал очень простой скрипт Python, который изменяет случайные байты в файле БД и проверяет, как SQLite будет с этим справляться:
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'
Результаты показали, что «редактирование» данных таблицы таким способом вполне возможно:
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
Как правило, интересно видеть, что выполнение запроса не удалось для половины модификаций, которые не были обнаружены при проверке целостности, но самое интересное для меня - то, что что-то может поменять случайные байты при рендеринге моей БДмое приложение бесполезно для части моих пользователей.
Я читал о возможных причинах повреждения на веб-сайте SQLite, а также на StackOverflow, я знаю, что, например, принудительное закрытие приложения может нанести вред БД.Я просто хотел бы знать, возможно ли реализовать быструю и более надежную проверку целостности БД.
Я читаю данные из одного столбца всей таблицы при запуске (для автозаполнения), поэтому яЯ думал о вычислении некоторого хэша из всех значений - я думаю, что это будет работать довольно хорошо, поскольку некоторые хэш-функции предназначены только для проверки целостности, но, возможно, есть более простое, быстрое и лучшее решение - поэтому я спрашиваю вас, если вызнаю любой.