2012-01-23 70 views
6

起初,一些背景:更好的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上的腐敗的可能原因,我知道例如強制關閉應用程序可能會損害數據庫。我只想知道是否可以實現快速和更強大的數據庫完整性檢查。我想從所有值計算一些哈希值 - 我認爲這將工作相當不錯,因爲一些哈希函數是設計只是爲了做完整性檢查,但也許有一個更簡單,更快,更好的解決方案 - 我因此問你,如果你知道的話。

+0

正如在這個問題的答案建議:http://stackoverflow.com/questions/11490250/does-sqlite-checksum-its-data 你可以使用前向糾錯來編碼你的數據。也許不是簡單或更快(哈希似乎是一個合理和簡單的解決方案),但也許更好。你實際上有機會糾正錯誤,而不僅僅是檢測錯誤。 – bsa

+0

這個問題有點老了,但我想提到[這個答案](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'的更快版本。**啊。 –

回答

1

我不知道任何這樣的SQLite功能,所以我會說計算散列是最簡單的解決方案,請看MessageDigest類的開始。