3

ディスクファイルを更新する書き込みを行うアプリがありますが、ファイルの以前のバージョンが破損しないように、可能な限り確認したいと思います。

もちろん、ファイルを更新する最も簡単な方法は、次のように書くことです。

(spit "myfile.txt" mystring)

ただし、書き込み中にPC(またはJavaプロセス)が停止した場合、ファイルが破損する可能性はわずかです。

より良い解決策は、おそらく次のように書くことです。

(do (spit "tempfile" mystring)
    (.rename (file "tempfile") "myfile.txt")
    (delete-file "tempfile"))

これは、ほとんどの場合、単一のストレージデバイスで実行される場合、通常はアトミックであるjavaファイルの名前変更関数を使用します。

ClojureファイルIOについてある程度の知識を持っているClojurianは、これが最善のアプローチであるかどうか、またはディスクファイルを更新する際のファイル破損のリスクを最小限に抑えるためのより良い方法があるかどうかについてアドバイスがありますか?

ありがとう!

4

3 に答える 3

2

これはClojureに固有のものではありません。temp-rename-deleteシナリオは、POSIX標準でのアトミック置換を保証するものではありません。これは、書き込みの並べ替えの可能性があるためです。一時的な書き込みが行われる前に名前が物理ディスクに到達する可能性があるため、この時間枠内に電源障害が発生すると、データが失われます。これは純粋に理論的な可能性ではありません。

http://en.wikipedia.org/wiki/Ext4#Delayed_allocation_and_potential_data_loss

一時ファイルを書き込んだ後、fsync()が必要です。この質問では、Javaからのfsync()の呼び出しについて説明します。

于 2013-03-04T19:44:55.480 に答える
1

あなたが与える例は、私の理解では完全に慣用的で正しいものです。前の実行が失敗した場合に備えて、最初に一時ファイルを削除し、エラー検出を追加します。

于 2013-03-04T19:34:04.907 に答える
1

コメントからのフィードバックに基づいて、いくつかの観察に基づいて、独自のファイルバックアップデータベースをロールしようとしないことをお勧めします。

  • クラッシュの場合に一貫性のあるファイルシステム内のデータ構造の永続的なストレージは、解決するのが難しい問題です。多くの本当に賢い人々がこの問題について考えることに多くの時間を費やしてきました。
  • 小さなデータベースは大きなデータベースに成長し、時間の経過とともに追加の機能を収集する傾向があります。自分で転がすと、プロジェクトの過程で車輪の再発明をしていることに気付くでしょう。

クラッシュが発生した場合にアプリケーションのデータの一貫性を維持することに本当に関心がある場合は、無料で利用できる多くのデータベースの1つを埋め込むことを検討することをお勧めします。まず、Berkely DB、HyperSQLを検討します。 、またはよりClojureフレーバーを持つものの場合はDatomic。

于 2013-03-04T20:10:54.627 に答える