簡単な例/いいえ質問「有効」を使用して、最後のスナップショット以降にZFSデータセットが変更されたことをどのように確認できますか?

簡単な例/いいえ質問「有効」を使用して、最後のスナップショット以降にZFSデータセットが変更されたことをどのように確認できますか?

tank名前付きデータセットに名前付きプールがあるとしますdatadata名前付きスナップショットも1つ以上ありますlast_snapshot

tank
tank/data
tank/data@last_snapshot

diff私が知っている限り、データセットが変更されたことを確認する「遅い」方法は、次の出力を確認することです。

zfs diff tank/data@last_snapshot

最後のスナップショット以降、個々のファイル/フォルダごとのデータセットのすべての変更が表示されます。このコマンドは多くの出力を生成でき、変更が多い場合は数秒または数分間実行できます。

より速いが(私が知る限り)信頼性が低い方法は、writtenデータセットのプロパティを調べることです。

tank/data written 72K -
tank/data@last_snapshot written 1,83G -

データセット(スナップショットではない)writtenの値が56〜128kの場合、データセットは通常最後/最も最近のスナップショット以降は変更されませんでした。この方法ははるかに高速ですが、なぜ数字がそんなに変わるのか理解していないので、この方法に頼りたくありません。

安全かつ迅速にはい/いいえ質問をするにはどうすればよいですか?最後のスナップショット以降、データセットが変更/変更されましたか?


デザイン哲学(背景):私は数週間に一度の「大きな」変更をまれに受け取るかなりの量のデータセットを持っています。 1 日に 1 回スナップショットを作成し、最後のスナップショット(例:7)を維持すると、最後の「重要な」変更前の状態がすばやく失われる可能性があります。私が念頭に置いたのは次のとおりです。 「重要な」変更が発生した場合にのみスナップショットを撮り、最後の7つを維持します。

答え1

これは良い質問であり、今私ができることは「賛成」に投票するだけです。

この問題について考えると、私が試したいくつかの推測方法は次のとおりです。

  • データセットのスナップショットを再作成し、両方のスナップcreatetxgショットの(「作成」)属性を比較します。 1つのテストでは、幸運で連続した値がありました(snapA生成とsnapB生成間の切り替え中にトランザクションが発生しなかったことを意味します)。さらなる調査によると、トランザクショングループはファイルシステム固有の番号ではなくプール全体にグローバルに番号が付けられているため、これは後で役に立たないことがわかりました。

  • createtxgスナップショットの値をファイルシステムの最新のトランザクショングループと比較します。わかりませんが、スナップショットがファイルシステムcreatetxgの最新のトランザクショングループと同じかそれよりも高い場合、スナップショットの作成自体がそのファイルシステムにコミットされた最新のトランザクションであることを推測できます。これが本当かどうかはわかりませんが、スナップショットが「オリジナル」であるかどうかを正確に判断するために、スナップショットをcreatetxgファイルシステムの最新のスナップショットと比較することがtxgできれば、予想外のことになります。

この時点で私が提供できる最善の答えは、writtenファイルシステムの属性を信頼することです。ただし、厳格なパラメータ内でのみ可能です。

1) 保留中のすべてのトランザクションがファイルシステムにコミットされていることを確認します。

sync; sleep 1; sync  # maybe I'm just being superstitious?

2)ファイルシステムが非アクティブ(マウントされていない)であることを確認してください。

zfs umount tank/data

written3)-p次のフラグを使用して、マシンが分析できる属性の正確な値を照会します。zfs list

zfs list -Hpo written tank/data

スナップショットがオリジナルであると推論するには、この数字は正確にゼロでなければなりません。 「小さい」と入れると足りないzfsマニュアルページ額面のまま:

次の基本プロパティには、データセットの読み取り専用統計情報が含まれています。これらのプロパティは設定または継承できません。特に明記しない限り、デフォルト属性はすべてのデータセットタイプに適用されます。
...

createtxg

データセットが生成されるトランザクショングループ(txg)。ブックマークには、createtxg元のバインドされたスナップショットと同じ内容があります。この属性は、増分送受信などのスナップショットのリストをソートするのに適しています。
...

written

最後のスナップショット以降にこのデータセットに書き込まれた参照スペースの量。

追加の予定は次のとおりです。

written@snapshot

指定されたスナップショット以降にこのデータセットに書き込まれる参照スペースの量。これは、このデータセットで参照されているが指定されたスナップショットでは参照されないスペースです。

値がゼロであることを確認し、その状態に対するアクションを開始しようとしたときに競合状態が発生しないようにファイルシステムをマウント解除する必要がありますが、同時に他のプロセスがファイルシステムに書き込み、パーティーがクラッシュしようとしたとき。

最近コミットされたトランザクショングループ番号に対してファイルシステムを照会する方法を知っている人がいる場合は、その方法を知る必要があります。基本的なインターネット検索では役に立つと思われる内容は出ませんでした。

もう1つの興味深い属性は、referencedスナップショットとその親ファイルシステムの属性です。

referenced

このデータセットにアクセスできるデータ量は、プール内の他のデータセットと共有または共有されない可能性があります。スナップショットまたはレプリカが作成されると内容は同じであるため、最初は作成されたファイルシステムまたはスナップショットと同じスペースを参照します。

しかし、私の直感は、ファイルシステムとスナップショットの両方が10Gのデータを参照できますが、ディスクの実際のブロックの10Gと同じではないため、このプロパティも間違った希望を生み出すということです。 「いいえ」という意味です。「共有」というreferenced値が一致することは、十分な条件ではなく、要件に近いようです。

全体的に謙虚さと不確実性が多いので、スナップショットがオリジナルであるとzfs list仮定する前に、この出力に固執する必要があると思います。

# zfs create -o mountpoint=/root/test w541/test
# zfs snap w541/test@snap1
# zfs list -po written,written@snap1 w541/test
WRITTEN  WRITTEN@SNAP1
      0              0

汚れたスナップショットはもうきれいではありません。

# touch test/foo
# zfs list -po written,written@snap1 w541/test
WRITTEN  WRITTEN@SNAP1
  57344          57344

ロールバックすると再びきれいになります。

# zfs rollback w541/test@snap1
# zfs list -po written,written@snap1 w541/test
WRITTEN  WRITTEN@SNAP1
      0              0

ただし、最高の整合性を実現するには、プロパティを照会する前に、おそらく一定時間ファイルシステムをアンマウントする必要がありますwritten

間違った家庭、監督、または善意の人々が提供した追加の洞察を修正していただきありがとうございます。

答え2

後で参考にするために、次のロジックを採用しました。集中的なテストを受けた結果、正常に動作しているようです。しかし、より良い答えとアイデアは非常に感謝します。参考までに以下もご覧ください。zfs-discussメーリングリストに関するディスカッション

for dataset in tree:

    # If there is no snapshot for this dataset, make one ...
    if len(dataset['SNAPSHOTS']) == 0:
        make_snapshot(dataset)
        continue

    # If nothing has been written, no snapshot is required.
    if dataset['written'] == 0:
        continue

    # If written is north of 1 MByte, make a snapshot.
    if dataset['written'] > (1024 ** 2):
        make_snapshot(dataset)
        continue

    # If the dataset is not a filesystem and
    # we got this far, make a snapshot.
    if dataset['type'] == 'volume':
        make_snapshot(dataset)
        continue

    # Only filesystems with less than 1 MByte written left.
    # Let's look at the diff of the last snapshot.
    diff_out = run_command([
        'zfs', 'diff',
        dataset['NAME'] + '@' + dataset['SNAPSHOTS'][-1]['NAME']
        ])

    # If the diff is not empty, make a snapshot.
    if len(diff_out.strip(' \t\n')) > 0:
        make_snapshot(dataset)

答え3

bash以下は、必要に応じて変更できる再帰プールに対してこれを処理するスクリプトです。

function processChanges() {
        POOL=$1
        ROWS=$(zfs get -Hr written ${POOL} |grep -v @ |awk '{print $1 "|" $3}' |grep -v "${POOL}|")
        for ROW in ${ROWS}; do
                CHANGED=0
                V=${ROW##*|}
                P=${ROW%%|*}
                echo -n "Checking ${P}... "
                if [ "${V: -1}" = "K" ]; then
                        BYTES_CHANGED=$(echo "${V:0:-1} * 1024" |bc )
                elif [ "${V: -1}" = "M" ]; then
                        BYTES_CHANGED=$(echo "${V:0:-1} * 1024 * 1024" |bc )
                elif [ "${V: -1}" = "G" ]; then
                        BYTES_CHANGED=$(echo "${V:0:-1} * 1024 * 1024 * 1024" |bc )
                else
                        BYTES_CHANGED=${V}
                fi
                BYTES_CHANGED=${BYTES_CHANGED%%.*}
                MEG=$(( 1 * 1024 * 1024 ))
                if [ ${BYTES_CHANGED} -gt ${MEG} ]; then
                        CHANGED=1;
                elif [ ${BYTES_CHANGED} -ne 0 ]; then
                        LASTSNAP=$(zfs list -t snap ${P} |grep ${P} |sort |tail -n1)
                        LASTSNAP=$(echo ${LASTSNAP##*@}); LASTSNAP=$(echo ${LASTSNAP%% *});
                        DIFF=$(zfs diff ${P}@${LASTSNAP})
                        if [ "${DIFF}" != "" ]; then
                                CHANGED=2;
                        fi
                fi
                if [ ${CHANGED} -gt 0 ]; then
                        echo "Changed"
                else
                        echo "No changes"
                fi
        done
}

processChanges s/storage

関連情報