2012-01-23 6 views
6

は、いくつかの背景:より良いSQLiteの破損を検出

マイのAndroidアプリは、4列の行の多くのDBテーブルを持っています。これはサーバーに要求を送信し、サーバーはこれらの4つの値のすべてが「有効」である場合にのみ応答します。数千人のユーザーのうちの何人かは、何かが彼らのために働いていないと報告しました。(しばらくして、サーバーから結果が得られないので) - 問題の原因を突き止めようとしていました。 DBの破損が検出されていません。

ACRAログにはSQLエラーメッセージがありますが、これはアプリケーションが破損しているためにファイルを開くことができないということです。それは私にいくつかの手がかりを与えましたが、私はまだこれが問題であると確信していませんでした。

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' 

結果はこのように「編集」テーブルのデータが完全に可能であることを示した::だから、私はSQLiteのは、それに対処する方法をランダムDBファイル内のバイトとチェックを変更する非常に単純なPythonスクリプトを作成し

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の破損の原因について読んだことがあります。アプリケーションを強制終了するとDBに害を及ぼすことがあります。高速でより堅牢なDBの整合性チェックを実装できるかどうかを知りたいだけです。

私はスタートアップ時(オートコンプリート用)にテーブル全体の1列からデータを読み込んでいるので、すべての値からハッシュを計算することを考えました - これはかなりうまくいくと思います。完全性チェックのためだけに設計されていますが、おそらく単純で高速で優れたソリューションがあります。わかっていれば、あなたに尋ねています。

+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'のより速いバージョンだと言います。** Ah。 –

答えて

1

私はこのようなSQLiteの機能を知らないので、ハッシュを計算するのが最も簡単な解決策だと言えば、開始のためにMessageDigestクラスを見てください。

関連する問題