同期書き込みは成功したが、最新の TXG はまだコミットされていない。また、現在のファイルを削除しても、スペースが完全に解放されない。ZFS において、これらの2つの現象はそれぞれリカバリ根拠と共有参照 によって説明され、「キャッシュがあるから」という単純な説明では不十分である。
説明すべき現象 該当セクション
4台のディスクで任意の2台の故障に耐えられるか? 第1~2節:プールと vdev
同期成功後のリカバリ根拠は何か? 第3節:TXG と ZIL のタイムライン
SLOG、L2ARC、special vdev は互いに交換可能か? 第4節:デバイスの役割
スナップショットがスペースを保持する理由、整合性チェックがバックアップと同等でない理由 第5~7節:参照帳とリカバリ能力
1. pool、vdev、dataset の階層
オブジェクト 役割 混同してはならない概念
pool スペースの割り当てを一元化し、プールレベルの状態を管理する ディレクトリ1つに相当するわけではない
トップレベル data vdev データの割り当てと自身の冗長性を担当する 複数のトップレベル vdev が自動的にミラーリングされるわけではない
mirror / RAIDZ vdev メンバーデバイスの冗長レイアウトを構成する 冗長性の許容範囲は通常、各 vdev ごとに分析される
filesystem dataset ファイルディレクトリ、属性、クォータ、スナップショットなどの管理境界 個別のパーティションは不要だが、プールのリソースを共有する
zvol ブロックデバイスを公開する volume dataset 通常のディレクトリツリーを直接提供するわけではない
snapshot / clone 履歴状態の保持 / スナップショットに基づく書き込み可能な派生 別の障害ドメインの完全なバックアップに相当するわけではない
プールが2つの2ディスクミラーからなるトップレベル vdev で構成されていると仮定し、グループごとに故障を判断する:
故障の分布 各グループにコピーが残っているか? 典型的な結果
各グループで1台ずつ故障 あり 通常、サービス継続可能
同一グループで2台とも故障 そのグループにはなし プールが利用不能になる可能性がある
同じ2台の故障でも、位置が異なれば結果が異なる。RAIDZ も同様に、グループごとのレイアウト、実際のエラー、残りのコピー数に基づいて分析する必要がある。詳細はプールと vdev の概念 を参照。
2. ソフトウェア層はすべてのリクエストが順次通過するパイプラインではない
ZPL は POSIX ファイル操作を Linux VFS に接続し、DMU はオブジェクト、データバッファ、トランザクションを管理し、SPA および vdev 関連層はストレージプールの割り当てと低レベル I/O を処理する。ARC はキャッシュ機構であり、ZIL は同期意図ログであり、これらを DMU と SPA の間に必須の直列層として描くべきではない。
OpenZFS は Linux 上でカーネル外モジュールを提供しており、DKMS またはディストリビューションのプリコンパイルモジュールを使用してインストールできる。SPL は主に必要なカーネル環境と抽象化を適応させるものであり、あらゆるライセンスの組み合わせを自動的に有効にする法的変換層ではない。OpenZFS は CDDL を使用しており、公開およびパッケージ化についてはライセンスの説明 および対象ディストリビューションの方針を参照すること。「決してマージされない」というのは現在の事実に基づかない主張であり、技術的な結論としては不適切である。
ARC と Linux のマップ/ページキャッシュパスとの相互作用は実装バージョンに依存し、ZFS が Linux ページキャッシュを全く関与させないと単純に断言することはできない。通常ファイル、mmap、zvol、ダイレクト I/O も、同じ読み書き関数チェーンに無理やり当てはめるべきではない。
3. TXG:一貫したブロック参照のグループをコミットする
変更はまずメモリ内のオブジェクト状態に入り、トランザクショングループに追加される。TXG を同期化する際、データおよび影響を受けるメタデータパスが書き出され、最後に識別可能な有効なルート状態が確立される。リカバリはブロック整合性チェック、順序、有効な uberblock などのメカニズムに依存しており、すべてのブロックポインタの書き込みが本質的にアトミックであるわけでも、任意のセクタのティアリングが問題ないわけでもない。
TXG は複数の変更を集約してコストを分散する。open、quiescing、syncing などのフェーズにより、異なるグループの作業がオーバーラップ可能になる。タイムアウトパラメータはトリガー条件の一つに過ぎず、ダーティデータの圧力なども同期を促進するため、1回の write を「ちょうど5秒後に1つのアトミックトランザクション」と対応付けることはできない。ファイルシステムトランザクションの境界は、アプリケーションのマルチステップなビジネス境界と自動的に一致するわけではない。
同期リクエストと TXG:まずリカバリ根拠を確立し、その後通常のディスク書き込みを完了する
アプリケーション同期書き込み / fsync
メモリ内の変更
トランザクショングループ TXG に追加
必要な ZIL レコードをコミット
プール内または独立した SLOG に配置可能
同期リクエストは返却可能
リカバリ保証が満たされた
TXG を通常ストレージに書き込み
有効な新しいルートをコミット
対応するログを回収可能
再度のリカバリは不要
これは典型的な ZIL パスです。同期済み TXG などの場合はログへの再書き込みは不要です。周期は固定された損失ウィンドウではありません。
同期リクエストは通常、ZIL を使用してクラッシュ後に再実行可能な根拠を確立し、毎回大型の TXG の完全な同期を待つ必要はない。その後、対応するデータは通常の TXG パスを通じて通常ストレージに書き込まれ、リカバリ時には、すでにコミット済み TXG で上書きされていないログが必要な分だけ再実行される。ZIL レコードには書き込みデータが含まれる場合もあれば、すでに書き出されたブロックを参照する場合もあり、「操作名のみを保存し、データを一切保存しない」と言うことはできない。
TXG と ZIL を同じリカバリタイムラインに配置する
すでに安定してコミットされた TXG 100 において、ファイルのある範囲の内容が O であると仮定する。アプリケーションが同期変更 W₁ を実行し、それを N に書き換える。その後、別の範囲の通常非同期変更 W₂ が実行されたが、W₂ に対して同期リクエストは行われなかった。sync=standard であり、ストレージデバイスが書き込みおよび同期の保証に従うものと仮定する。
クラッシュの位置 安定したリカバリ根拠 これに基づいて保証できること
W₁ の同期リクエストがまだ成功して返されていない 少なくとも TXG 100 がある;ログの完全性は進行状況に依存する W₁ を確認済み更新として扱うことはできない
W₁ に必要なログが安定し、同期呼び出しが成功;新しい TXG はまだコミットされていない TXG 100 と再実行可能な W₁ ログ 古いルートをリカバリ後、必要なログを再実行し、確認済みの W₁ を保持する
TXG 101 に W₁ が含まれ、安定してコミットされた 新しい有効なルートとその参照ブロック W₁ は通常のツリーによってすでに上書きされており、対応するログは回収可能
以下で変更範囲を選択し、同期書き込み、非同期書き込み、TXG コミットをインターリーブする。リカバリ結果は安定したルートとまだ再実行が必要なログから得られ、最新のメモリ内容は自動的にリカバリ根拠にはならない。
図を準備しています 再読み込み
同期書き込みがまだ TXG に含まれていない場合、リカバリはどのように行われるか? 確認済みの同期変更は、古い TXG と必要な ZIL レコードによって回復可能である。新しい TXG によって上書きされて初めて、これらのログは不要になる。非同期書き込みも TXG とともに永続化される可能性がある。
{"id":"zfs-txg-and-log-recovery","title":"同期書き込みがまだ TXG に含まれていない場合、リカバリはどのように行われるか?","summary":"確認済みの同期変更は、古い TXG と必要な ZIL レコードによって回復可能である。新しい TXG によって上書きされて初めて、これらのログは不要になる。非同期書き込みも TXG とともに永続化される可能性がある。","height":1000,"html":"<h2 data-i18n=\"heading\"></h2><p class=\"intro\" data-i18n=\"intro\"></p><div class=\"presets\" role=\"group\" data-i18n-label=\"choose\"><button data-mode=\"0\" data-i18n=\"a\"></button><button data-mode=\"1\" data-i18n=\"b\"></button></div><div class=\"actions\"><button id=\"sync\" data-i18n=\"sync\"></button><button id=\"asyncWrite\" data-i18n=\"asyncWrite\"></button></div><div class=\"track-row\"><span data-i18n=\"memory\"></span><div id=\"memory\" class=\"track\"></div></div><div class=\"track-row\"><span data-i18n=\"root\"></span><div id=\"root\" class=\"track\"></div></div><div class=\"track-row\"><span data-i18n=\"log\"></span><div id=\"log\" class=\"track\"></div></div><div class=\"actions\"><button id=\"commit\" data-i18n=\"commit\"></button><button id=\"crash\" data-i18n=\"crash\"></button></div><div class=\"track-row\"><span data-i18n=\"recovery\"></span><div id=\"recovery\" class=\"track\"></div></div><div class=\"copy\"><p id=\"explanation\" role=\"status\"></p><p class=\"reserve\" aria-hidden=\"true\" data-i18n=\"note\"></p></div><div class=\"actions\"><button id=\"reset\" data-i18n=\"reset\"></button></div><details class=\"scope\"><summary data-i18n=\"scopeLabel\"></summary><p data-i18n=\"scope\"></p></details>","css":".intro{margin:8px 0 18px;color:var(--muted);font-size:14px}.caption,.hint{font-size:12px;color:var(--muted);margin-top:12px}.control{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:6px 12px;align-items:center;margin:14px 0;font-size:13px}.control label{font-size:13px}.control output{color:var(--accent);min-width:5em;text-align:right;font-variant-numeric:tabular-nums}.control input{grid-column:1/-1;width:100%;margin:0}.presets{display:flex;gap:4px;align-items:stretch}.presets button{flex:1 1 0;min-width:0;overflow-wrap:anywhere;font-size:13px}.actions{display:flex;gap:8px;flex-wrap:wrap;margin:14px 0}.actions button{flex:1;min-width:0;font-size:13px;min-height:42px}.copy{display:grid;font-size:14px;margin:16px 0}.copy>*{grid-area:1/1;margin:0}.reserve{visibility:hidden}.scope{margin-top:14px;color:var(--muted);font-size:12px}.scope summary{padding:8px 0;cursor:pointer}.scope p{margin-top:10px}.two{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;margin:16px 0}.card{border:1px solid var(--rule);border-radius:9px;padding:14px;min-width:0}.card header{font-size:14px;font-weight:600;margin-bottom:10px}.card button{font-size:12px;width:100%;min-width:0}.card small{display:block;font-size:12px;color:var(--muted)}.card code{font-size:12px;overflow-wrap:anywhere}.metrics{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;margin:16px 0}.metrics>div{border-left:2px solid var(--accent);padding-left:10px;min-width:0}.metrics span{display:block;min-height:3.2em;color:var(--muted);font-size:12px}.metrics strong{font-size:23px;display:block;font-weight:500;overflow-wrap:anywhere;font-variant-numeric:tabular-nums}.formula{border-top:1px solid var(--rule);padding-top:12px;margin-top:14px;font-size:13px;font-variant-numeric:tabular-nums;overflow-wrap:anywhere}.value{font:500 20px var(--viz-font-ui)}.legend{display:flex;flex-wrap:wrap;gap:6px 14px;font-size:12px;color:var(--muted);margin:12px 0}.legend span:before{content:'';display:inline-block;width:8px;height:8px;border-radius:2px;background:var(--accent);margin-right:6px}.legend .second:before{background:var(--second)}.check{display:flex;align-items:center;gap:8px;font-size:13px;margin:12px 0}.check input{width:16px;height:16px;flex-shrink:0;accent-color:var(--accent)}select,input[type=text],input[type=number]{background:var(--paper);color:var(--ink);font:inherit;font-size:13px;padding:10px;border:1px solid var(--rule);border-radius:7px;max-width:100%;min-width:0}select{width:100%;min-height:42px}.band{height:20px;display:flex;background:var(--surface);border-radius:4px;overflow:hidden}.band i{height:100%;display:block;background:var(--accent);transition:width .25s}.band i.second{background:var(--second)}button:disabled{cursor:default}.status{font-size:13px;min-height:4.8em}.mono{font-family:var(--viz-font-mono);font-variant-numeric:tabular-nums}.muted{color:var(--muted)}\n@media(max-width:480px){.two{gap:8px}.card{padding:12px 9px}.actions button,.presets button{font-size:12px}.metrics strong{font-size:20px}.metrics{gap:8px}}\n@media(prefers-reduced-motion:reduce){*,*::before,*::after{transition:none!important;animation:none!important}}\n.track-row{margin:16px 0}.track-row>span{display:block;font-size:12px;color:var(--muted);margin-bottom:7px}.track{display:flex;gap:5px;min-width:0}.cell{flex:1;min-width:0;min-height:48px;border:1px solid var(--rule);border-radius:5px;background:var(--surface);display:flex;align-items:center;justify-content:center;text-align:center;padding:5px 3px;font-size:12px;overflow-wrap:anywhere;font-variant-numeric:tabular-nums}.cell.on{background:var(--accent-soft);border-color:var(--accent)}.cell.gold{background:var(--second-soft);border-color:var(--second)}.cell.empty{border-style:dashed;color:var(--muted)}.cell.error{border-color:var(--second);text-decoration:line-through}.choices{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:6px;margin:14px 0}.choices button{min-width:0;padding:10px 4px;font-size:12px;overflow-wrap:anywhere}.choices button[aria-current=true]{border-color:var(--accent);background:var(--accent-soft)}.relation{display:grid;grid-template-columns:minmax(0,1fr) 28px minmax(0,1fr);align-items:center;gap:6px;margin:12px 0}.relation .cell{min-height:72px}.relation>i{text-align:center;font-style:normal;color:var(--accent)}.readout{font-size:13px;white-space:pre-line;min-height:6.4em;overflow-wrap:anywhere}.plot{position:relative;border-left:1px solid var(--rule);border-bottom:1px solid var(--rule);padding:8px 0;margin:18px 0}.plot-row{height:28px;position:relative;margin:4px 0;background:var(--surface)}.plot-row i{position:absolute;inset-block:5px;background:var(--accent);min-width:2px;transition:width .2s,left .2s}.plot-row b{position:relative;padding:4px 6px;font:11px/28px var(--viz-font-ui);background:var(--paper);border-radius:3px}.axis{display:flex;justify-content:space-between;font-size:11px;color:var(--muted)}\n\n","js":"const $=s=>document.querySelector(s);const set=(id,v)=>$('#'+id).textContent=v;const t=k=>viz.t(k);function cells(id,values){$('#'+id).replaceChildren(...values.map(v=>{const e=document.createElement('div');e.className='cell '+(v.cls||'');e.textContent=v.text;e.title=v.title||v.text;return e;}));}function pressed(mode){document.querySelectorAll('[data-mode]').forEach(e=>e.setAttribute('aria-pressed',String(e.dataset.mode===mode)));}let chosen=0,mem=[0,0],root=[0,0],log=[null,null],serial=0,dead=false;function draw(){for(const [id,arr]of Object.entries({memory:mem,root,log,recovery:dead?root.map((v,i)=>log[i]??v):[null,null]}))cells(id,arr.map((v,i)=>({text:(i?'B':'A')+': '+(v===null?'—':'v'+v),cls:id==='root'||id==='log'?'gold':v===null?'empty':'on'})));for(const id of ['sync','asyncWrite','commit','crash'])$('#'+id).disabled=dead;pressed(String(chosen));set('explanation',t('note'));}document.querySelectorAll('[data-mode]').forEach(e=>e.onclick=()=>{chosen=+e.dataset.mode;draw();});for(const id of ['sync','asyncWrite'])$('#'+id).onclick=()=>{mem[chosen]=++serial;if(id==='sync')log[chosen]=mem[chosen];draw();};$('#commit').onclick=()=>{root=[...mem];log=[null,null];draw();};$('#crash').onclick=()=>{dead=true;draw();};$('#reset').onclick=()=>{mem=[0,0];root=[0,0];log=[null,null];serial=0;dead=false;draw();};draw();","audio":false,"strings":{"a":"範囲 A","asyncWrite":"非同期書き込みで新しいバージョン","b":"範囲 B","choose":"書き込み範囲を選択","commit":"現在の TXG をコミット","crash":"クラッシュしてリカバリ","heading":"同期書き込みがまだ TXG に含まれていない場合、リカバリはどのように行われるか?","intro":"範囲 A または B を選択し、同期または非同期方式で新しいバージョンを書き込む。TXG をコミットするか、または直接クラッシュさせ、安定したルート、ログ、およびリカバリ内容を見比べる。","log":"保持が必要な ZIL レコード","memory":"メモリ内の現在の内容","note":"まず A に対して同期書き込みを行い、その後 A を非同期で変更してみる:古い確認済み値には依然としてリカバリ根拠があり、新しい非同期値はこれによって自動的に保護されるわけではない。","pending":"未実行のリカバリ","recovery":"リカバリ:まずルート、次に再実行","reset":"リセット","root":"コミット済みルートで上書きされた内容","scope":"2つの独立した範囲、sync=standard、デバイスは同期の保証を履行する。同期ボタンは書き込みと有効なログの安定化をアトミックに完了する。値は再実行可能な記録を表すが、実際のログフォーマットを表すものではない。クラッシュはルートまたはログで保護されていないすべての内容を破棄し、ログデバイスの同時故障はシミュレートしない。","scopeLabel":"モデル範囲と規約","sync":"同期書き込みで新しいバージョン"}}
非同期 W₂ を再考する:保証されていないからといって必ずしも消失するわけではない
W₂ の運命は「W₁ の後に発生したから」という理由だけで推論できない。もしそれが有効な TXG によって上書きされておらず、同期保証もない場合、消失する可能性がある。もしある TXG とともに安定してコミットされていれば、保持される可能性もある。非同期とは、アプリケーションがその返却ポイントで同じ永続性保証を得られないことを意味するだけであり、カーネルがそれが必ず消失すると保証するものではない。
このタイムラインは、COW と ZIL がそれぞれ何を供給するかを示している。COW の有効な古いルートにより、システムは一貫したブロック参照のセットに戻ることができる。ZIL は、アプリケーションに対して確認済みだが、まだ最新の通常のツリーに含まれていない同期操作を補完する。ログデバイスの低レイテンシは、後者のリカバリ根拠の確立速度に影響を与えるが、メインストレージが変更を書き出すことを永久に免れさせるものではない。
ログが消失した場合、どちらのリカバリ根拠が成立しなくなるか
まだ再実行が必要な唯一のログコピーが同時に消失した場合、2行目の証明は成立しなくなる。リスクの集合は「どの確認済み操作がまだそのログに依存しているか」によって決定され、固定された壁掛け時計の5秒でも、特定のパラメータ名だけで決定されるものでもない。冗長なログとデバイスの電源断保護の意義は、設計された故障条件下でもリカバリ根拠が存在し続けることにある。
4. ZIL、SLOG、L2ARC、special vdev
名称 役割 故障時にまず考慮すべきこと
ZIL 同期変更のリカバリログ機構 確認済みだが TXG で上書きされていない変更をどのようにリカバリするか
SLOG ZIL が使用する独立したログデバイス ログの冗長性、電源断保護、エラーおよびリカバリパス
ARC メモリキャッシュ(データ、メタデータなどを含む) メモリ圧力、キャッシュヒット率、ダーティデータのスロットリング
L2ARC / cache vdev ARC 以外のセカンダリ読み取りキャッシュ 消失後は通常、メインストレージから再読み込みされ、唯一のデータソースではない
special vdev メタデータなどの割り当て、設定によっては小データブロックも格納 クリティカルアロケーションデバイスであり、いつでも破棄できるキャッシュではない
SLOG は、任意の非同期の大容量ファイル書き込みを継続的な SSD 速度に変えるものではない。それは関連する同期リクエストのレイテンシパスを変更するだけであり、通常ストレージは TXG の書き出しを引き続き受け持つ。バックエンドの排出速度が長期間不足している場合、システムは最終的にスロットリングを行う。デバイスのレイテンシは、標称シーケンシャル帯域幅だけでなく、flush および電源断保護下の実際の挙動を見る必要がある。
ログデバイスを消失させ、さらにクラッシュが発生すると、アプリケーションに対して確認済みだが、まだログによるリカバリが必要な変更が破損する可能性がある。「直近の固定5秒のみが消失し、非同期書き込みは影響を受けない」とは保証できない。実行中、インポート時、ログに冗長性があるかどうか、対応する TXG がコミットされたかどうかによって、結果は変化する。関連するデバイスの役割についてはOpenZFS ハードウェア説明 を参照。
sync=standard はアプリケーションの同期リクエストに従い、sync=always は同期要件を拡大し、sync=disabled はこの種の通常の永続性要件を無視する。disabled のパフォーマンスを通常の fsync のパフォーマンスと直接比較することは、異なる保証を比較するものであり、同じ安全条件下でより高速であることを証明するものではない。属性のセマンティクスについては zfsprops(7) を参照。
5. スナップショット、レコードサイズ、スペースの保持
スナップショットは古いブロック参照を保持し、クローンではスナップショットを基に書き込み可能なブランチを生成できる。ファイルが元のブロック A、B を持っており、スナップショット作成後、現在のバージョンが A を A′ に変更したと仮定する。古い A は依然としてスナップショットによって参照されている。現在のファイルを削除しても、A、B が必ずしも回収されるとは限らない。プールの使用量と、あるディレクトリのファイルの論理サイズは、共有、圧縮、スナップショット、メタデータにより異なる。
スペースの帳:512 KiB ファイルがなぜ 640 KiB を保持しているか
モデルを制限する。ファイルは4つの 128 KiB レコード A、B、C、D で構成されており、メタデータ、圧縮、パディング、追加コピーは無視する。スナップショット S を作成後、2つのビューはこれら4つのレコードを共有する。現在のファイルは A を A′ に書き換える。
1回のレコード書き換え:2つのビュー、合計5つのレコードを保持
スナップショット S
現在のファイル
A
B
C
D
A′
B、C、D は引き続き共有
5 × 128 KiB = 640 KiB
各ビューの論理長は依然として 512 KiB です。メタデータ、圧縮、パディング、追加コピーは無視します。
状態 現在のファイルの論理サイズ 2つのビューが合計で保持する
スナップショット作成後 512 KiB A、B、C、D、合計 512 KiB
A の書き換え後 512 KiB A、A′、B、C、D、合計 640 KiB
追加の占有は、履歴の A 依然として参照されていることに由来し、ファイルの論理長が大きくなったからではない。
この時点で現在のファイルを削除しても、S が残っている限り、古い A、B、C、D には依然として参照がある。S を削除して現在のファイルを残す場合、古い A は対応する回収が完了後に解放される。実際の統計には他のオーバーヘッドや共有関係も含まれるため、この数字を直接適用することはできないが、参照帳の推論方法は同じである。ファイルの論理サイズは統計内容のビューを、プールの使用量は保持が必要な実際のストレージを統計する 。これにより、スナップショットの作成直後は安価だが、長期間頻繁に書き換えられると多くの履歴ブロックを保持する可能性がある理由が説明される。
レコードサイズ:レイアウト属性は必ずしも毎回のデバイスリクエストサイズではない
recordsize はファイルシステムのデータレコードサイズに関連する属性であり、volblocksize は zvol に使用される。これらは「各アプリケーションの write が必ず同じサイズのデバイスリクエストを発行する」ことを意味するものではない。小範囲のランダム書き換え、圧縮、COW、既存のファイルレイアウトは増幅に影響を与える。属性の変更は、すべての古いファイルを即時書き換えることとして単純に扱うことはできない。チューニングの前に、ワークロードの読み書き範囲と同期頻度を明確にする必要がある。
キャッシュの観測:ヒット率だけでなく同期のロングテールも見る
ARC は最近/頻繁にアクセスされたデータやゴースト履歴などの情報に基づいてキャッシュ戦略を調整する。ゴーストレコードは、完全なデータをもう1つ保存するものではない。ARC のヒット率が高くても、少量の同期書き込みのロングテールレイテンシを隠蔽する可能性があるため、ワークロードごとに分離して観察する必要がある。L2ARC にはインデックス、パディング、メモリオーバーヘッドがあり、それを拡大しても、ホットスポットワークセット以外のすべてのパフォーマンス問題が自動的に解決されるわけではない。
6. 整合性チェック、scrub、resilver、バックアップ
メカニズム 主に解決する問題
整合性チェック 内容の不整合を検出し、正しいコピーがある場合は修復をサポートする
scrub アロケート済みデータの整合性を能動的にチェックする
resilver 必要な冗長性を回復する
スナップショットと独立したバックアップ 対応する履歴リカバリと障害ドメインの保護を提供する
内容が整合性チェックに合格したからといって、アプリケーションが書き込んだビジネス意味が正しいことを意味するものではなく、正常に実行された誤削除を取り消すものでもない。
ファイルシステムスナップショットはストレージ層のタイムポイントビューを提供するが、データベースのメモリ状態を外部システムと同時にコミットするものではない。アプリケーション一貫性のあるリカバリポイントは、データベースバックアップインターフェース、チェックポイント、または明示的な調整プロトコルを必要とする。
send/receive はスナップショット状態または差分を転送し、別のプールまたは別のホストのコピーを構築できる。インクリメンタルチェーンには、一致するベースと保持ポリシーが必要である。送信ストリームを生成できるからといって、回復可能なバックアップが完了したことを意味するものではなく、受信側の可用性とリカバリプロセスは依然として検証する必要がある。
7. ARC の読み取り専用読み取り、プールへの変更なし
from pathlib import Path
path = Path ( " /proc/spl/kstat/zfs/arcstats" )
if not path . exists ( ) :
print ( " ARC 統計が公開されていません。OpenZFS が読み込まれていない可能性があります" )
else :
values = { }
for line in path . read_text ( ) . splitlines ( ) :
columns = line . split ( )
if len ( columns ) == 3 and columns [ 2 ] . isdigit ( ) :
values [ columns [ 0 ] ] = int ( columns [ 2 ] )
for name in ( " size" , " c" , " c_min" , " c_max" , " hits" , " misses" ) :
print ( name , values . get ( name , " 提供されていません" ) )
hits , misses = values . get ( " hits" , 0 ) , values . get ( " misses" , 0 )
if hits + misses :
print ( " 累積ヒット率:" , hits / ( hits + misses ) )
ここでは累積比率であり、指定されたワークロード時間の差分に代わるものではない。zpool status はトポロジとエラーを理解するために使用し、zpool iostat はデバイス/プールのアクティビティのために使用し、zfs get は実際の属性と継承元を確認するために使用する。トポロジ、属性、ビジネスロードと組み合わせて観測を解釈し、設定の変更が必要かどうかを決定する。