起初,一些背景:更好的SQLite的腐敗檢測
我的Android應用有大量的四列列數據表。它將請求發送到服務器,並且服務器僅在所有這四個值均爲「有效」時才作出響應。成千上萬的用戶中有幾個報告說有些東西對他們來說不起作用(因爲有一段時間他們沒有從服務器獲得結果) - 我試圖找出導致問題的原因,結果發現唯一可能的原因是未檢測到數據庫損壞。
在ACRA日誌中,我收到了一些帶有SQL錯誤的消息,但這些消息是關於應用程序無法打開文件,因爲它被損壞了。這給了我一些線索,但我仍然不相信這是問題。所以,我創建了一個非常簡單的Python腳本,它改變了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
這是一般有趣的是,運行查詢失敗,一路上完整性檢查未被發現修改的一半,但對我來說最有趣的是,一些可換在我的DB隨機字節使我的應用程序無用我的用戶的一部分。
我讀過SQLite網站和StackOverflow上的腐敗的可能原因,我知道例如強制關閉應用程序可能會損害數據庫。我只想知道是否可以實現快速和更強大的數據庫完整性檢查。我想從所有值計算一些哈希值 - 我認爲這將工作相當不錯,因爲一些哈希函數是設計只是爲了做完整性檢查,但也許有一個更簡單,更快,更好的解決方案 - 我因此問你,如果你知道的話。
正如在這個問題的答案建議:http://stackoverflow.com/questions/11490250/does-sqlite-checksum-its-data 你可以使用前向糾錯來編碼你的數據。也許不是簡單或更快(哈希似乎是一個合理和簡單的解決方案),但也許更好。你實際上有機會糾正錯誤,而不僅僅是檢測錯誤。 – bsa
這個問題有點老了,但我想提到[這個答案](http://stackoverflow.com/questions/12418600/how-do-you-determine-if-an-sqlite-or-sqback-is- corrupt-in-java)提到使用'PRAGMA quick_check;'顯然對數據(?)*進行某種掃描*。我很好奇這會在上面的測試用例中得到什麼樣的結果,但我不確定你將如何整合它。 **編輯:[文檔](http://www.sqlite.org/pragma.html#pragma_integrity_check)說'quick_check'是'identity_check'的更快版本。**啊。 –