私のデータベースは約25 MBであり、データベースにアクセスするユーザー名とファイルのアクセス権が数か月間変更されていないことを確認しました。 「データベースまたはディスクがいっぱいです」が原因でクエリが失敗し、その後「データベースディスクイメージの形式が正しくない」という問題が発生する問題があります。
私がこれを間違って読んでいない限り、私のディスクはどこも満杯に近い場所ではありません(これがUbuntuサーバー9.10で、違いがあれば)
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/sda1 19610300 2389596 16224560 13% /
udev 10240 128 10112 2% /dev
none 254136 0 254136 0% /dev/shm
none 254136 36 254100 1% /var/run
none 254136 0 254136 0% /var/lock
none 254136 0 254136 0% /lib/init/rw
テストとして、新しいレコードを追加するアクションを実行しましたが、問題ありません。失敗しているアクションの特定のセットがある場合、私はfiめようとしています。ただし、挿入後(および挿入されていることを確認した後)、データベースのディスク上のバイト数は変更されていません(アップでもダウンでもありません)。
コマンドラインユーティリティを使用すると、次のような結果になります。
SQLite version 3.6.12
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> pragma integrity_check;
*** in database main ***
On tree page 2 cell 0: 2nd reference to page 26416
On tree page 2 cell 1: 2nd reference to page 26417
On tree page 2 cell 2: 2nd reference to page 26434
On tree page 2 cell 3: 2nd reference to page 26449
On tree page 2 cell 4: 2nd reference to page 26464
On tree page 2 cell 5: 2nd reference to page 26358
On tree page 2 cell 6: 2nd reference to page 26494
On tree page 2 cell 7: Child page depth differs
On tree page 2 cell 8: 2nd reference to page 26190
On tree page 2 cell 8: Child page depth differs
... etc., etc. ...
次はどこを見ればいいのか?テーブルの最大行数などに問題はありますか?私はSQLite3の最大値を読んでみましたが、私の知る限り、データベースには何もありません。
次に、毎日のバックアップを調べましたが、データベースのバックアップのファイルサイズが3〜4日間変わらないことがわかりました。非常に奇妙です。データベースのバックアップコピーを、ファイルサイズが変わらないうちから復元しましたが、依然として奇妙な問題が発生しています。
(1)古いバックアップから復元し、(2)修正するためにRails移行を再実行する必要があります。
考慮すべき事項:
SQLite3 DBファイルは、DBページサイズの倍数で大きく成長し、VACUUM
を使用しない限り縮小しません。一部の行を削除すると、解放されたスペースは内部的にマークされ、後の挿入で再利用されます。したがって、挿入によって、バッキングDBファイルのサイズが変更されることはほとんどありません。
SQLite(またはその他のデータベース)の従来のバックアップツールは、破損していないデータベースを確保するために重要なDB状態情報を考慮しないため、使用しないでください。特に、挿入トランザクションの途中でDBファイルをコピーすることは、災害のレシピです...
SQLite3には、使用中のデータベースのバックアップまたはコピー専用の [〜#〜] api [〜#〜] があります。
はい、DBファイルは 破損 のようです。ハードウェア/ファイルシステムのエラーの可能性があります。または、使用中にそれらをコピーしたのでしょうか?または、適切に取得されなかったバックアップを復元した可能性がありますか?
破損したデータベースを修復するには、sqlite3コマンドラインユーティリティを使用できます。環境変数を設定した後、シェルで次のコマンドを入力します。
cd $DATABASE_LOCATION
echo '.dump'|sqlite3 $DB_NAME|sqlite3 repaired_$DB_NAME
mv $DB_NAME corrupt_$DB_NAME
mv repaired_$DB_NAME $DB_NAME
このコードは、Core Dataの永続ストアとして使用するSQLiteデータベースの回復に役立ち、保存時に次のエラーが発生しました。
保存できませんでした:NSError 259ドメインNSCocoaErrorDomain {NSFilePath = mydata.db NSUnderlyingException =致命的エラー。 mydata.dbのデータベースが破損しています。 SQLiteエラーコード:11、「データベースディスクイメージの形式が正しくありません」}
不正な形式のsqliteファイルを修復するには、次のスクリプトを使用します。
#!/bin/bash
cat <( sqlite3 "$1" .dump | grep "^ROLLBACK" -v ) <( echo "COMMIT;" ) | sqlite3 "fix_$1"
ほとんどの場合、sqliteデータベースの形式が正しくない場合でも、ダンプを作成できます。このダンプは基本的に、データベースを再構築する多くのSQLステートメントです。
ダンプから一部の行が欠落している可能性があります(おそらく破損しているため)。この場合、欠落している行のINSERTステートメントはいくつかのコメントに置き換えられ、スクリプトはROLLBACK TRANSACTIONで終了します。
したがって、ここで行うことは、ダンプを作成し(不正な形式の行は除外されます)、ROLLBACKをCOMMITに置き換えて、ロールバックの代わりにダンプスクリプト全体がコミットされるようにすることです。
この方法は私の人生をすでに数百倍節約しました\ o /
そもそも「データベースまたはディスクがいっぱい」にならないようにするには、RAMが多い場合はこれを試してください。
sqlite> pragma temp_store = 2;
これは、SQLiteに一時ファイルをメモリに配置するように指示します。 (「データベースまたはディスクがいっぱいです」というメッセージは、データベースがいっぱいであることもディスクがいっぱいであることも意味しません!一時ディレクトリがいっぱいであることを意味します。)256GのRAM/tmpなので、これは私には最適です。 RAMが多いほど、使用できるdbファイルが大きくなります。
あなたが多くのラムを持っていない場合は、これを試してください:
sqlite> pragma temp_store = 1;
sqlite> pragma temp_store_directory = '/directory/with/lots/of/space';
temp_store_directoryは非推奨です(temp_storeは非推奨ではなくtemp_store_directoryを必要とするため、これはばかげています)。したがって、コードでこれを使用する場合は注意してください。
データベースが破損したときにこれが起こるのを見ましたが、新しいデータベースにクローンを作成しようとしましたか?
SQLiteデータベースを安全にコピーする
SQLiteデータベースは簡単にコピーできます。破損しない方法でこれを実行するのはそれほど簡単ではありません。方法は次のとおりです。
Shell$ sqlite3 some.db sqlite> begin immediate; <press CTRL+Z> Shell$ cp some.db some.db.backup Shell$ exit sqlite> rollback;
これにより、コピープロセスの途中でデータベースに書き込むことができないため、適切な状態であることが確実なNice Cleanバックアップが得られます。
google App Engineを使用しているときに、この問題が発生しました。何らかの理由で、その後Google App Engineが起動しなかったのでフォローしました。
$ echo '' > /tmp/appengine.apprtc.root/*.db
それを修正するには、手動で行う必要があります:
$ sqlite3 datastore.db
sqlite> begin immediate;
<press CTRL+Z>
$ cp datastore.db logs.db
次に、フラグ付きでGoogle App Engineを実行します。
$ dev_appserver.py --clear_datastore --clear_search_index
その後、ようやく機能しました。
アプリの開発中、メッセージは頻繁かつ大規模なINSERTおよびUPDATE操作からのものであることがわかりました。単一の操作で複数の行またはデータを挿入および更新してください。
var updateStatementString : String! = ""
for item in cardids {
let newstring = "UPDATE "+TABLE_NAME+" SET pendingImages = '\(pendingImage)\' WHERE cardId = '\(item)\';"
updateStatementString.append(newstring)
}
print(updateStatementString)
let results = dbManager.sharedInstance.update(updateStatementString: updateStatementString)
return Int64(results)