Лучшее обнаружение повреждения SQLite

6

Сначала, некоторый фон:

В моем Android приложении есть таблица БД с множеством четырех столбцов. Он отправляет запросы на сервер, а сервер отвечает только тогда, когда все эти четыре значения являются "действительными". Несколько тысяч пользователей сообщили, что для них что-то не работает (с тех пор как они не получают результаты с сервера) - я пытался выяснить, что вызывает проблему, и оказалось, что единственной возможной причиной является Повреждение DB, которое не обнаружено.

В журналах ACRA у меня есть сообщения с ошибками SQL, но это касается того, что приложение не может открыть файл из-за его повреждения. Это дало мне некоторое представление, но я все еще не был уверен, что это проблема. Итак, я создал очень простой Python script, который меняет случайные байты в файле DB и проверяет, как 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, я знаю, что, например, принудительное закрытие приложения может нанести вред БД. Я просто хотел бы знать, возможно ли реализовать быструю и надежную проверку целостности базы данных.

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

  • 0
    Как предлагается в ответе на этот вопрос: stackoverflow.com/questions/11490250/… Вы можете кодировать свои данные, используя прямое исправление ошибок. Может быть, не проще или быстрее (хеш кажется разумным и простым решением), но, возможно, лучше. У вас действительно будет шанс исправить ошибки, а не просто обнаружить их.
  • 0
    Этот вопрос немного старый, но я хотел упомянуть, что в этом ответе упоминается PRAGMA quick_check; который, по-видимому, выполняет какое-то сканирование данных (?) . Мне интересно, какие результаты это дало бы в приведенном выше тестовом примере, но я не уверен, как вы интегрируете его. РЕДАКТИРОВАТЬ: документация говорит, что quick_check является более быстрой версией identity_check . Ах.
Теги:
corrupt
integrity

1 ответ

1

Я не знаю какой-либо SQLite-функции, подобной этой, поэтому я бы сказал, что вычисление хэша является самым простым решением, взгляните на MessageDigest для начала.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню