假设我有一个名为的池tank
和一个名为的数据集data
。还有至少一张data
named 的快照last_snapshot
:
tank
tank/data
tank/data@last_snapshot
Run Code Online (Sandbox Code Playgroud)
确定数据集是否已更改的“慢”方法是检查 的输出diff
,据我所知:
zfs diff tank/data@last_snapshot
它将显示自上次快照以来每个文件/文件夹对数据集的所有更改。如果有大量更改,此命令会产生大量输出并运行几秒钟甚至几分钟。
一种更快但(据我所知)不太可靠的方法是查看written
数据集的属性:
tank/data written 72K -
tank/data@last_snapshot written 1,83G -
Run Code Online (Sandbox Code Playgroud)
如果written
数据集(不是任何快照)的值介于 56 和 128k 之间,则数据集通常自上次/最近的快照以来没有被修改。这要快得多,但不明白为什么这个数字会变化如此之大,我不想依赖这种方法。
如何安全快速地提出是/否问题:自上次快照以来,数据集是否已更改/修改?
设计理念(背景):我确实有相当数量的数据集,它们很少会收到“重大”变化,比如每两周一次。每天制作一次快照并保留最后一次,例如 7 次,很快会导致丢失最后一次“重大”更改之前的状态。这就是我想的地方:如果有“重大”变化,让我们只制作快照并保留其中的最后 7 个。
这是一个好问题,我现在能做的就是投赞成票。
在思考这个问题时,我尝试过的一些猜测途径是:
再次对数据集进行快照,并比较createtxg
两个快照的(“出生”)属性。在一次测试中,我很幸运并且具有连续的值(这意味着在创建 snapA 和创建 snapB 之间的过渡期间没有发生任何事务)。这个事实后来被证明毫无价值,因为进一步的研究告诉我,事务组在整个池中全局编号,而不是在每个文件系统中唯一编号。
createtxg
将快照的值与文件系统的最新事务组进行比较。我不确定,但如果快照createtxg
等于或高于文件系统的最新事务组,则可以推断快照创建本身是已提交到该文件系统的最新事务。我不确定这是否属实,但如果可以将快照createtxg
与文件系统的最新快照进行比较txg
以精确确定快照是否“原始”,那将是偶然的。
此时,我能提供的最佳答案是信任written
文件系统的属性,但仅限于严格的参数范围内:
1)确保所有待处理的事务已提交到文件系统
sync; sleep 1; sync # maybe I'm just being superstitious?
Run Code Online (Sandbox Code Playgroud)
2) 确保文件系统处于非活动状态(未安装)
zfs umount tank/data
Run Code Online (Sandbox Code Playgroud)
written
3)使用以下-p
标志查询属性的确切机器可解析值zfs list
zfs list -Hpo written tank/data
Run Code Online (Sandbox Code Playgroud)
在我推断快照是原始的之前,该数字必须恰好为 0。zfs
如果我们仅从手册页的表面来看,“小”还不够好:
以下本机属性包含有关数据集的只读统计信息。这些属性既不能设置,也不能继承。除非另有说明,本机属性适用于所有数据集类型。
...
createtxg
在其中创建数据集的事务组 (txg)。
createtxg
书签与它们最初绑定的快照具有相同的内容。此属性适合对快照列表进行排序,例如增量发送和接收。
...
written
自上一个快照以来写入此数据集的引用空间量。
进一步的承诺是:
written@snapshot
自指定快照以来写入此数据集的引用空间量。这是此数据集引用但指定快照未引用的空间。
需要卸载文件系统,以便在您注意到该值为 0 并开始对该状态采取行动之间不存在竞争条件,而同时另一个进程即将写入文件系统并破坏您的聚会。
如果有人知道如何查询文件系统最近提交的事务组号,我有义务知道该方法。一些基本的谷歌搜索没有找到任何我认为有用的东西。
另一个有趣的属性是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
Run Code Online (Sandbox Code Playgroud)
弄脏了快照,它就不再原始了:
# touch test/foo
# zfs list -po written,written@snap1 w541/test
WRITTEN WRITTEN@SNAP1
57344 57344
Run Code Online (Sandbox Code Playgroud)
将其滚回去,它又变得原始了:
# zfs rollback w541/test@snap1
# zfs list -po written,written@snap1 w541/test
WRITTEN WRITTEN@SNAP1
0 0
Run Code Online (Sandbox Code Playgroud)
但为了获得最高的完整性,在查询属性之前,应该卸载文件系统,也许需要卸载一段时间written
。
我将非常感谢任何人对任何错误的假设、疏忽或任何好心人提供的额外见解的纠正。