> For the complete documentation index, see [llms.txt](https://book.bsdcn.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://book.bsdcn.org/handbook/di-23-zhang-z-wen-jian-xi-tong-zfs/23.3.-zpool-guan-li.md).

# 23.3.zpool 管理

ZFS 管理使用两个主要工具。`zpool` 工具控制池的操作，允许添加、移除、替换和管理磁盘。`zfs` 工具允许创建、销毁和管理数据集，包括文件系统和卷。

## 23.3.1. 创建和销毁存储池

创建 ZFS 存储池时，最重要的决策是将物理磁盘分组为哪种类型的 vdev。有关可用选项的详情，请参阅 [vdev 类型](/handbook/di-23-zhang-z-wen-jian-xi-tong-zfs/23.10.-zfs-te-xing-he-shu-yu.md) 列表。vdev 类型决定池的冗余、容量和性能特征。池的布局并非在创建时永久固定。镜像允许向 vdev 添加新磁盘，条带通过将新磁盘附加到 vdev 升级为镜像。RAID-Z vdev 借助 [RAID-Z 扩展](#id-23.3.4.-raid-z-kuo-zhan) 一次扩展一块磁盘，该功能需要 OpenZFS 2.3 或更高版本，首次出现在 FreeBSD 15.0 中。添加新 vdev 可随时扩展池，在限定条件下也支持[移除顶层 vdev](#id-23.3.3.-tian-jia-he-yi-chu-she-bei)。对运行中的池进行重塑需要消耗时间和 I/O 带宽，因此预先选择合适的 vdev 类型仍然重要。

创建简单的镜像池，磁盘上包含 `freebsd-zfs` 类型的 GPT 分区：

```sh
# zpool create mypool mirror /dev/ada1p1 /dev/ada2p1
# zpool status
  pool: mypool
 state: ONLINE
config:

        NAME        STATE     READ WRITE CKSUM
        mypool      ONLINE       0     0     0
          mirror-0  ONLINE       0     0     0
            ada1p1  ONLINE       0     0     0
            ada2p1  ONLINE       0     0     0

errors: No known data errors
```

要在单个命令中创建多个 vdev，请指定由 vdev 类型关键字（此示例中为 `mirror`）分隔的磁盘组：

```sh
# zpool create mypool mirror /dev/ada1p1 /dev/ada2p1 mirror /dev/ada3p1 /dev/ada4p1
# zpool status
  pool: mypool
 state: ONLINE
config:

        NAME        STATE     READ WRITE CKSUM
        mypool      ONLINE       0     0     0
          mirror-0  ONLINE       0     0     0
            ada1p1  ONLINE       0     0     0
            ada2p1  ONLINE       0     0     0
          mirror-1  ONLINE       0     0     0
            ada3p1  ONLINE       0     0     0
            ada4p1  ONLINE       0     0     0

errors: No known data errors
```

池也可以使用分区，而不是整个磁盘。将 ZFS 放入单独的分区可以使同一磁盘具有其他分区，用于其他目的。特别是，它能添加具有引导代码和引导所需文件系统的分区，使得可以从同时作为池成员的磁盘引导。在 FreeBSD 上使用分区而不是整个磁盘不会对性能造成额外负担。使用分区还能让管理员 *欠配* 磁盘，即使用比整个磁盘容量少的空间。如果未来替换的磁盘与原始磁盘的名义大小相同，但实际容量略小，较小的分区仍然可以适应替换磁盘。

使用分区创建 [RAID-Z2](/handbook/di-23-zhang-z-wen-jian-xi-tong-zfs/23.10.-zfs-te-xing-he-shu-yu.md) 池：

```sh
# zpool create mypool raidz2 /dev/ada0p1 /dev/ada1p1 /dev/ada2p1 /dev/ada3p1 /dev/ada4p1 /dev/ada5p1
# zpool status
  pool: mypool
 state: ONLINE
config:

        NAME        STATE     READ WRITE CKSUM
        mypool      ONLINE       0     0     0
          raidz2-0  ONLINE       0     0     0
            ada0p1  ONLINE       0     0     0
            ada1p1  ONLINE       0     0     0
            ada2p1  ONLINE       0     0     0
            ada3p1  ONLINE       0     0     0
            ada4p1  ONLINE       0     0     0
            ada5p1  ONLINE       0     0     0

errors: No known data errors
```

ZFS 根据 vdev 的 `ashift` 值（扇区大小的以 2 为底的对数）对齐并按大小执行对每个 vdev 的最小写入。OpenZFS 在创建 vdev 时检测磁盘报告的扇区大小，并据此选择 `ashift`。某些驱动器为了兼容性报告 512 字节扇区，而内部使用 4096 字节扇区。在此类驱动器上创建池时，使用显式的 `-o ashift=12` 强制 4096 字节对齐：

```sh
# zpool create -o ashift=12 mypool mirror /dev/ada1p1 /dev/ada2p1
```

将 **sysctl(8)** 变量 `vfs.zfs.vdev.min_auto_ashift` 设置为 `12`，在池创建及随后的 `zpool add` 和 `zpool attach` 操作中可获得相同结果。`ashift` 是每个 vdev 的属性，而非整个池的属性。它在创建 vdev 时固定，之后无法更改，因此在向池提交数据前请验证此值。

销毁不再需要的池以重新利用磁盘。销毁池之前需要先卸载该池中的文件系统。如果某个数据集正在使用中，卸载操作会失败，无法销毁池。使用 `-f` 强制销毁池。这可能会导致应用程序出现未定义行为，特别是当应用程序有打开的文件时。

## 23.3.2. 池属性

与数据集一样，池也有属性用于报告状态和控制行为。使用 `zpool get all <mypool>` 显示池的所有属性，或指定具体的属性：

```sh
# zpool get health,capacity mypool
NAME    PROPERTY  VALUE   SOURCE
mypool  health    ONLINE  -
mypool  capacity  27%     -
```

使用 `zpool set` 修改可写属性：

```sh
# zpool set comment="Backup pool" mypool
# zpool get comment mypool
NAME    PROPERTY  VALUE        SOURCE
mypool  comment   Backup pool  local
```

像 `size`、`capacity`、`fragmentation` 和 `health` 这样的属性是只读状态值。其他属性会改变池的行为；本章使用 `autoexpand` 自动扩展池（见 [扩展池](#id-23.3.16.-kuo-zhan-chi)），`autoreplace` 配合热备（见 [热备与 zfsd 自动替换](#id-23.3.11.-re-bei-yu-zfsd-zi-dong-ti-huan)），`autotrim` 用于 SSD 池（见 [TRIM 与初始化](#id-23.3.14.-trim-yu-chu-shi-hua)），以及 `compatibility` 用于可移植池（见 [升级存储池](#id-23.3.18.-sheng-ji-cun-chu-chi)）。在创建池时通过向 `zpool create` 传递 `-o` 设置属性，如上面对 `ashift` 的示例所示。**zpoolprops(7)** 描述了每个池属性。

## 23.3.3. 添加和移除设备

有两种方法可以将磁盘添加到池中：通过 `zpool attach` 将磁盘附加到现有的 vdev，或者通过 `zpool add` 向池中添加 vdev。一些 [vdev 类型](/handbook/di-23-zhang-z-wen-jian-xi-tong-zfs/23.10.-zfs-te-xing-he-shu-yu.md) 在创建后能向 vdev 添加磁盘。RAID-Z vdev 只能通过 [RAID-Z 扩展](#id-23.3.4.-raid-z-kuo-zhan) 接受新磁盘。

使用单个磁盘创建的池没有冗余。它可以检测到损坏，但无法修复，因为没有数据的其他副本。[copies](/handbook/di-23-zhang-z-wen-jian-xi-tong-zfs/23.10.-zfs-te-xing-he-shu-yu.md) 属性可能从小的故障（例如坏道）中恢复，但它不像镜像或 RAID-Z 那样提供相同级别的保护。从一个由单个磁盘 vdev 组成的池开始，使用 `zpool attach` 将新磁盘添加到 vdev，创建镜像。也可以使用 `zpool attach` 将新磁盘添加到镜像组中，从而增加冗余和读取性能。在为池的磁盘分区时，将第一个磁盘的布局复制到第二个磁盘。使用 `gpart backup` 和 `gpart restore` 可以简化这一过程。

通过附加 `ada1p3`，将单个磁盘（条带）vdev `ada0p3` 升级为镜像：

```sh
# zpool status
  pool: mypool
 state: ONLINE
config:

        NAME        STATE     READ WRITE CKSUM
        mypool      ONLINE       0     0     0
          ada0p3    ONLINE       0     0     0

errors: No known data errors
# zpool attach mypool ada0p3 ada1p3
Make sure to wait until resilver is done before rebooting.
# gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 ada1
partcode written to ada1p1
bootcode written to ada1
# zpool status
  pool: mypool
 state: ONLINE
status: One or more devices is currently being resilvered.  The pool will
        continue to function, possibly in a degraded state.
action: Wait for the resilver to complete.
  scan: resilver in progress since Sat Jul 11 11:15:25 2026
        738M scanned at 105M/s, 522M issued at 74.6M/s, 781M total
        522M resilvered, 66.84% done, 00:00:03 to go
config:

        NAME        STATE     READ WRITE CKSUM
        mypool      ONLINE       0     0     0
          mirror-0  ONLINE       0     0     0
            ada0p3  ONLINE       0     0     0
            ada1p3  ONLINE       0     0     0  (resilvering)

errors: No known data errors
# zpool status
  pool: mypool
 state: ONLINE
  scan: resilvered 781M in 00:00:16 with 0 errors on Sat Jul 11 11:18:36 2026
config:

        NAME        STATE     READ WRITE CKSUM
        mypool      ONLINE       0     0     0
          mirror-0  ONLINE       0     0     0
            ada0p3  ONLINE       0     0     0
            ada1p3  ONLINE       0     0     0

errors: No known data errors
```

当向现有的 vdev 添加磁盘不可行时（例如 RAID-Z），替代方法是向池中添加另一个 vdev。通过将写入分配到各个 vdev 上，添加 vdev 提供了更高的性能。每个 vdev 提供其自身的冗余。可以混合使用 `mirror` 和 `RAID-Z` 类型的 vdev，但不推荐这样做。向包含镜像或 RAID-Z vdev 的池中添加非冗余 vdev 会使整个池的数据面临风险。分布式写入意味着，如果非冗余磁盘发生故障，将导致写入池的每个块的一部分丢失。

ZFS 将数据条带化到每个 vdev 上。例如，使用两个镜像 vdev，这实际上是 RAID 10，将写入条带化到两个镜像组上。ZFS 会分配空间，以确保每个 vdev 在相同时间达到 100% 满。拥有不同可用空间的 vdev 会降低性能，因为更多的数据写入会到达较少满的 vdev。

向引导池附加新设备时，请记得更新引导代码。

将第二个镜像组（`ada2p3` 和 `ada3p3`）附加到现有的镜像：

```sh
# zpool status
  pool: mypool
 state: ONLINE
  scan: resilvered 781M in 00:00:16 with 0 errors on Sat Jul 11 12:11:56 2026
config:

        NAME        STATE     READ WRITE CKSUM
        mypool      ONLINE       0     0     0
          mirror-0  ONLINE       0     0     0
            ada0p3  ONLINE       0     0     0
            ada1p3  ONLINE       0     0     0

errors: No known data errors
# zpool add mypool mirror ada2p3 ada3p3
# gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 ada2
partcode written to ada2p1
bootcode written to ada2
# gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 ada3
partcode written to ada3p1
bootcode written to ada3
# zpool status
  pool: mypool
 state: ONLINE
  scan: resilvered 781M in 00:00:16 with 0 errors on Sat Jul 11 09:58:28 2026
config:

        NAME        STATE     READ WRITE CKSUM
        mypool      ONLINE       0     0     0
          mirror-0  ONLINE       0     0     0
            ada0p3  ONLINE       0     0     0
            ada1p3  ONLINE       0     0     0
          mirror-1  ONLINE       0     0     0
            ada2p3  ONLINE       0     0     0
            ada3p3  ONLINE       0     0     0

errors: No known data errors
```

`zpool add` 还能向现有池附加专用日志设备和缓存设备。[log](/handbook/di-23-zhang-z-wen-jian-xi-tong-zfs/23.10.-zfs-te-xing-he-shu-yu.md) vdev 将 ZFS intent log 存放在独立的低延迟存储上，加速数据库和 NFS 等发出的同步写入。日志设备应当镜像，因为丢失未镜像的日志设备并伴随系统崩溃会让池损失最后几秒的同步写入；有关容量规划和调优指南，请参阅“同步写入、ZIL 与 SLOG”一节。[cache](/handbook/di-23-zhang-z-wen-jian-xi-tong-zfs/23.10.-zfs-te-xing-he-shu-yu.md) vdev 在快速存储上为 [ARC](/handbook/di-23-zhang-z-wen-jian-xi-tong-zfs/23.10.-zfs-te-xing-he-shu-yu.md) 扩展第二级读取缓存。缓存设备无需冗余，因为 ZFS 在从缓存读取失败时会改从原始池磁盘读取该块。缓存的内容（即 [L2ARC](/handbook/di-23-zhang-z-wen-jian-xi-tong-zfs/23.10.-zfs-te-xing-he-shu-yu.md)）默认在重启后仍然保留。

向现有池添加镜像日志 vdev 和 NVMe 缓存设备：

```sh
# zpool add mypool log mirror ada4p2 ada5p2
# zpool add mypool cache nda0p2
# zpool status mypool
  pool: mypool
 state: ONLINE
  scan: resilvered 781M in 00:00:16 with 0 errors on Sat Jul 11 09:58:28 2026
config:

        NAME        STATE     READ WRITE CKSUM
        mypool      ONLINE       0     0     0
          mirror-0  ONLINE       0     0     0
            ada0p3  ONLINE       0     0     0
            ada1p3  ONLINE       0     0     0
          mirror-1  ONLINE       0     0     0
            ada2p3  ONLINE       0     0     0
            ada3p3  ONLINE       0     0     0
        logs
          mirror-2  ONLINE       0     0     0
            ada4p2  ONLINE       0     0     0
            ada5p2  ONLINE       0     0     0
        cache
          nda0p2    ONLINE       0     0     0

errors: No known data errors
```

`zpool detach` 在剩余冗余足够的情况下，可以从镜像 vdev 中移除单个磁盘。如果一个镜像组中只剩一个磁盘，该组将不再是镜像，而变成条带，如果该磁盘发生故障，将危及整个池的数据。

从三重镜像组中移除磁盘：

```sh
# zpool status
  pool: mypool
 state: ONLINE
  scan: scrub repaired 0B in 00:01:11 with 0 errors on Sat Jul 11 03:14:02 2026
config:

        NAME        STATE     READ WRITE CKSUM
        mypool      ONLINE       0     0     0
          mirror-0  ONLINE       0     0     0
            ada0p3  ONLINE       0     0     0
            ada1p3  ONLINE       0     0     0
            ada2p3  ONLINE       0     0     0

errors: No known data errors
# zpool detach mypool ada2p3
# zpool status
  pool: mypool
 state: ONLINE
  scan: scrub repaired 0B in 00:01:11 with 0 errors on Sat Jul 11 03:14:02 2026
config:

        NAME        STATE     READ WRITE CKSUM
        mypool      ONLINE       0     0     0
          mirror-0  ONLINE       0     0     0
            ada0p3  ONLINE       0     0     0
            ada1p3  ONLINE       0     0     0

errors: No known data errors
```

`zpool remove` 从池中移除整个顶层 vdev。ZFS 通过将已分配数据复制到池中的其他 vdev 来疏散该 vdev，然后断开磁盘。移除适用于热备、缓存、日志、special 和 dedup 设备，以及由单磁盘或镜像组成的数据 vdev。包含顶层 RAID-Z vdev 的池无法移除数据 vdev，且池中所有顶层 vdev 必须使用相同的 `ashift`。疏散在后台运行，池始终保持在线；使用 `zpool status` 监视进度。移除完成后，ZFS 会保留一张内存中的表，将已移除 vdev 的块映射到新位置。该表很小但是永久存在的；`zpool remove -n` 可在开始移除前估算其内存占用。

从池中移除两个镜像 vdev 中的一个：

```sh
# zpool remove mypool mirror-1
# zpool status mypool
  pool: mypool
 state: ONLINE
  scan: scrub repaired 0B in 00:01:11 with 0 errors on Sat Jul 11 03:14:02 2026
remove: Evacuation of mirror in progress since Sat Jul 11 10:15:31 2026
        1.71G copied out of 2.32G at 111M/s, 73.71% done, 0h0m to go
config:

        NAME        STATE     READ WRITE CKSUM
        mypool      ONLINE       0     0     0
          mirror-0  ONLINE       0     0     0
            ada0p3  ONLINE       0     0     0
            ada1p3  ONLINE       0     0     0
          mirror-1  ONLINE       0     0     0
            ada2p3  ONLINE       0     0     0
            ada3p3  ONLINE       0     0     0

errors: No known data errors
# zpool status mypool
  pool: mypool
 state: ONLINE
  scan: scrub repaired 0B in 00:01:11 with 0 errors on Sat Jul 11 03:14:02 2026
remove: Removal of vdev 1 copied 2.32G in 0h0m, completed on Sat Jul 11 10:15:53 2026
        10.9K memory used for removed device mappings
config:

        NAME          STATE     READ WRITE CKSUM
        mypool        ONLINE       0     0     0
          mirror-0    ONLINE       0     0     0
            ada0p3    ONLINE       0     0     0
            ada1p3    ONLINE       0     0     0
          indirect-1  ONLINE       0     0     0

errors: No known data errors
```

`indirect-1` 条目是已移除 vdev 重映射块的占位符，不包含任何磁盘。使用 `zpool remove -s` 可取消进行中的移除。

## 23.3.4. RAID-Z 扩展

RAID-Z 扩展一次向现有 RAID-Z vdev 添加一块磁盘，不改变其奇偶校验等级。

> **注意**
>
> RAID-Z 扩展需要 OpenZFS 2.3 或更高版本，首次出现在 FreeBSD 15.0 中。在更早版本上创建的池需要先使用 `zpool upgrade` 启用 `raidz_expansion` 特性才能扩展。

要扩展 RAID-Z vdev，运行 `zpool attach` 并指定 `zpool status` 显示的 RAID-Z vdev 名称和新磁盘：

```sh
# zpool attach mypool raidz2-0 ada6p3
```

扩展在后台将现有数据回流到扩大后的磁盘集，池保持在线和使用中。添加 `-w` 让 `zpool attach` 等待扩展完成。`zpool status` 在 `expand:` 行报告进度：

```sh
# zpool status mypool
  pool: mypool
 state: ONLINE
  scan: scrub repaired 0B in 06:14:36 with 0 errors on Sat Jul 11 04:31:19 2026
expand: expansion of raidz2-0 in progress since Sat Jul 11 09:42:12 2026
        1.83T / 5.36T copied at 186M/s, 34.14% done, 05:31:43 to go
config:

        NAME        STATE     READ WRITE CKSUM
        mypool      ONLINE       0     0     0
          raidz2-0  ONLINE       0     0     0
            ada0p3  ONLINE       0     0     0
            ada1p3  ONLINE       0     0     0
            ada2p3  ONLINE       0     0     0
            ada3p3  ONLINE       0     0     0
            ada4p3  ONLINE       0     0     0
            ada5p3  ONLINE       0     0     0
            ada6p3  ONLINE       0     0     0

errors: No known data errors
```

扩展完成后，新磁盘的容量变为可用：

```sh
# zpool status mypool | grep expand:
expand: expanded raidz2-0 copied 5.36T in 08:23:35, on Sat Jul 11 18:05:47 2026
```

扩展前写入的块保持原有的数据与奇偶校验比例，并按此占用空间。因此，新磁盘带来的完整容量增益只适用于扩展后写入的数据；旧数据只有在被重写时才能受益，例如使用 `zfs rewrite`。重复此过程可一次添加一块磁盘，从而将 vdev 扩展多块磁盘。

## 23.3.5. dRAID 池

dRAID 是 RAID-Z 的一种变体，它将热备容量分散到 vdev 中的所有磁盘上。[dRAID](/handbook/di-23-zhang-z-wen-jian-xi-tong-zfs/23.10.-zfs-te-xing-he-shu-yu.md) vdev 由内部 RAID-Z 组和可选的 *分布式热备* 构成，二者均匀分布在每块磁盘上。当一块磁盘发生故障时，ZFS 通过并行读写其余所有磁盘向分布式热备中重建，完成时间远短于向单个热备磁盘重新同步的过程。随后替换故障磁盘，从分布式热备重建该磁盘，恢复完整保护。dRAID 面向拥有大量磁盘、RAID-Z 重建时间长得危险的池。

vdev 类型完整描述了布局，详见 **zpoolconcepts(7)**：

```sh
draid[parity][:datad][:childrenc][:sparess]
```

`parity` 是内部组的奇偶校验等级，取值 1 到 3，默认为 1。`data` 是每个冗余组中数据设备的数量，默认为 8。`children` 是磁盘总数，在列出大量设备时用作交叉校验。`spares` 是分布式热备的数量，默认为 0。

创建一个由 24 块磁盘组成的 dRAID vdev 池，双奇偶校验，每个冗余组 8 块数据磁盘，2 个分布式热备：

```sh
# zpool create mypool draid2:8d:24c:2s ada0 ada1 ada2 ada3 ada4 ada5 ada6 ada7 ada8 ada9 ada10 ada11 ada12 ada13 ada14 ada15 ada16 ada17 ada18 ada19 ada20 ada21 ada22 ada23
```

分布式热备在 `zpool status` 中显示在 `spares` 下，名称类似 `draid2-0-0`，表示第一个 vdev 的第一个热备。

dRAID 以空间效率换取重建速度。与 RAID-Z 不同，dRAID 使用固定条带宽度，用零填充较小的写入。在默认的 8 块数据磁盘和 4 KB 扇区下，最小分配为 32 KB，这会降低以小块为主的数据集的可用容量和压缩效果。分布式热备的容量也是预先占用的，无论磁盘是否会发生故障。将 dRAID 池与 [special vdev](#id-23.3.6.-te-shu-fen-pei-lei) 搭配使用，可以将元数据和小块移出宽条带，恢复大部分损失的效率。对于只有少量磁盘的池，RAID-Z 仍然是更好的选择。

## 23.3.6. 特殊分配类

特殊分配类将 vdev 专用于特定类型的池数据。[special](/handbook/di-23-zhang-z-wen-jian-xi-tong-zfs/23.10.-zfs-te-xing-he-shu-yu.md) vdev 存储池元数据（如间接块和 dnode），可选地存储小文件的数据块。`dedup` vdev 存储[去重](/handbook/di-23-zhang-z-wen-jian-xi-tong-zfs/23.10.-zfs-te-xing-he-shu-yu.md)表。将此类元数据放在 NVMe 镜像等快速设备上，可以加速目录遍历、`zfs list` 以及在原本较慢磁盘组成的池上的去重查找等元数据密集型操作。

向现有池添加镜像 special vdev：

```sh
# zpool add mypool special mirror nda0 nda1
```

新的元数据分配随后会进入 special vdev；已有的元数据在未重写前保持在原处。

设置 `special_small_blocks` 数据集属性，可以让 special vdev 同时存储不超过指定大小的数据块：

```sh
# zfs set special_small_blocks=16K mypool/projects
```

有效值为零（禁止在 special 类中存储数据块）或 512 字节到 1 MB 之间的 2 的幂（适用于 FreeBSD 14.x）；FreeBSD 15.0 接受最大到 16 MB 的最大块大小的值。将该属性设置为数据集的 `recordsize` 会将该数据集的所有数据块发送到 special 类。当 special vdev 写满时，新的分配会回到普通类，而不会失败。

> **警告**
>
> special vdev 不是缓存。它持有分配给它的池元数据的唯一副本，丢失它会摧毁池。使 special 和 dedup vdev 的冗余与数据 vdev 的冗余相匹配，例如使用镜像。

使用 `zpool remove` 移除 special 或 dedup vdev 是可能的，但受[添加和移除设备](#id-23.3.3.-tian-jia-he-yi-chu-she-bei)中描述的限制约束。在实践中，当 special vdev 使用的设备扇区大小与数据 vdev 不同时，`ashift` 必须匹配的要求通常会阻止移除。

## 23.3.7. 检查池的状态

池的状态很重要。如果某个硬盘脱机或 ZFS 检测到读取、写入或校验和错误，相应的错误计数将增加。`status` 输出显示了池中每个设备的配置和状态，以及整个池的状态。还会显示要采取的操作以及上一次 [scrub](/handbook/di-23-zhang-z-wen-jian-xi-tong-zfs/23.10.-zfs-te-xing-he-shu-yu.md) 的详情。

```sh
# zpool status
  pool: mypool
 state: ONLINE
  scan: scrub repaired 0B in 02:25:36 with 0 errors on Sat Jul 11 06:51:26 2026
config:

        NAME        STATE     READ WRITE CKSUM
        mypool      ONLINE       0     0     0
          raidz2-0  ONLINE       0     0     0
            ada0p3  ONLINE       0     0     0
            ada1p3  ONLINE       0     0     0
            ada2p3  ONLINE       0     0     0
            ada3p3  ONLINE       0     0     0
            ada4p3  ONLINE       0     0     0
            ada5p3  ONLINE       0     0     0

errors: No known data errors
```

选项可根据任务调整输出：

* `-v` 显示详细的数据错误信息，打印自上次完整池 scrub 以来发现的所有错误的完整列表，包括受影响文件的名称。
* `-x` 只显示有错误的池或不可用的池，隐藏健康的池。
* `-s` 显示每个叶子 vdev 上的慢 I/O 操作数，即未在 30 秒内完成的操作。
* `-e` 只显示不健康的 vdev，使拥有大量设备的池输出更简短；此标志需要 FreeBSD 14.1 或更高版本。
* `-p` 以精确的、可解析的数值显示数字，而非四舍五入的人类可读形式。
* `-t` 显示每个 vdev 的 [TRIM](#id-23.3.14.-trim-yu-chu-shi-hua) 状态。

完整的选项列表请参阅 **zpool-status(8)**。

## 23.3.8. 清除错误

当检测到错误时，ZFS 会增加读取、写入或校验和错误计数。使用 `zpool clear <mypool>` 清除错误消息并重置计数。清除错误状态对于自动化脚本非常重要，因为这些脚本会在池遇到错误时提醒管理员。如果不清除旧错误，脚本可能会无法报告后续错误。

## 23.3.9. 替换正常的设备

有时可能希望用不同的硬盘替换磁盘。替换正常磁盘时，操作过程中会保持旧磁盘在线，池不会进入 [degraded](/handbook/di-23-zhang-z-wen-jian-xi-tong-zfs/23.10.-zfs-te-xing-he-shu-yu.md) 状态，从而减少数据丢失的风险。运行 `zpool replace` 将数据从旧磁盘复制到新磁盘。操作完成后，ZFS 会将旧磁盘从 vdev 中断开。如果新磁盘比旧磁盘大，可能使用新空间扩展 zpool，见 [扩展池](#id-23.3.16.-kuo-zhan-chi)。

替换池中的正常设备：

```sh
# zpool status
  pool: mypool
 state: ONLINE
config:

        NAME        STATE     READ WRITE CKSUM
        mypool      ONLINE       0     0     0
          mirror-0  ONLINE       0     0     0
            ada0p3  ONLINE       0     0     0
            ada1p3  ONLINE       0     0     0

errors: No known data errors
# zpool replace mypool ada1p3 ada2p3
Make sure to wait until resilvering finishes before rebooting.

When booting from the pool 'mypool', update the boot code on the newly attached disk 'ada2p3'.

Assuming GPT partitioning is used and ada0 is the new boot disk, use the following command:

        gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 ada0
# gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 ada2
# zpool status
  pool: mypool
 state: ONLINE
status: One or more devices is currently being resilvered.  The pool will
        continue to function, possibly in a degraded state.
action: Wait for the resilver to complete.
  scan: resilver in progress since Sat Jul 11 14:21:35 2026
        781M / 781M scanned, 604M / 781M issued at 101M/s
        604M resilvered, 77.39% done, 00:00:01 to go
config:

        NAME             STATE     READ WRITE CKSUM
        mypool           ONLINE       0     0     0
          mirror-0       ONLINE       0     0     0
            ada0p3       ONLINE       0     0     0
            replacing-1  ONLINE       0     0     0
              ada1p3     ONLINE       0     0     0
              ada2p3     ONLINE       0     0     0  (resilvering)

errors: No known data errors
# zpool status
  pool: mypool
 state: ONLINE
  scan: resilvered 781M in 00:00:17 with 0 errors on Sat Jul 11 14:21:52 2026
config:

        NAME        STATE     READ WRITE CKSUM
        mypool      ONLINE       0     0     0
          mirror-0  ONLINE       0     0     0
            ada0p3  ONLINE       0     0     0
            ada2p3  ONLINE       0     0     0

errors: No known data errors
```

在镜像 vdev 上，向 `zpool replace` 或 `zpool attach` 添加 `-s` 会执行 *顺序重同步*，而非愈合式重同步。顺序重同步按磁盘顺序复制数据，不验证每个块的校验和，从而更快地恢复冗余。由于复制跳过校验和验证，ZFS 会在顺序重同步完成后自动对池启动 [scrub](#id-23.3.12.-dui-chi-jin-xing-scrub)。顺序重同步适用于镜像和 [dRAID](#id-23.3.5.-draid-chi) vdev，不适用于 RAID-Z。使用 `zpool resilver <mypool>` 可从头重新启动进行中的重同步。

## 23.3.10. 处理故障设备

当池中的磁盘发生故障时，磁盘所在的 vdev 会进入 [degraded](/handbook/di-23-zhang-z-wen-jian-xi-tong-zfs/23.10.-zfs-te-xing-he-shu-yu.md) 状态。数据仍然可用，但性能会降低，因为 ZFS 会从可用的冗余数据中计算缺失的数据。为了将 vdev 恢复到完全正常的状态，需要替换故障的物理设备。然后会指示 ZFS 开始 [resilver](/handbook/di-23-zhang-z-wen-jian-xi-tong-zfs/23.10.-zfs-te-xing-he-shu-yu.md) 操作。ZFS 会从可用的冗余数据中重新计算故障设备的数据，并将其写入替换设备。操作完成后，vdev 会恢复到 [online](/handbook/di-23-zhang-z-wen-jian-xi-tong-zfs/23.10.-zfs-te-xing-he-shu-yu.md) 状态。

如果 vdev 没有冗余，或者设备出现故障且冗余不足以弥补，池会进入 [faulted](/handbook/di-23-zhang-z-wen-jian-xi-tong-zfs/23.10.-zfs-te-xing-he-shu-yu.md) 状态。除非有足够的设备重新连接池，否则池将无法使用，必须从备份中恢复数据。

在替换故障磁盘时，故障磁盘的名称会更改为新磁盘的 GUID。如果替换设备的名称与原设备相同，`zpool replace` 不需要指定新的设备名称。

使用 `zpool replace` 替换故障磁盘：

```sh
# zpool status
  pool: mypool
 state: DEGRADED
status: One or more devices could not be opened.  Sufficient replicas exist for
        the pool to continue functioning in a degraded state.
action: Attach the missing device and online it using 'zpool online'.
   see: https://openzfs.github.io/openzfs-docs/msg/ZFS-8000-2Q
config:

        NAME                    STATE     READ WRITE CKSUM
        mypool                  DEGRADED     0     0     0
          mirror-0              DEGRADED     0     0     0
            ada0p3              ONLINE       0     0     0
            316502962686821739  UNAVAIL      0     0     0  was /dev/ada1p3

errors: No known data errors
# zpool replace mypool 316502962686821739 ada2p3
# zpool status
  pool: mypool
 state: DEGRADED
status: One or more devices is currently being resilvered.  The pool will
        continue to function, possibly in a degraded state.
action: Wait for the resilver to complete.
  scan: resilver in progress since Sat Jul 11 14:52:21 2026
        781M / 781M scanned, 641M / 781M issued at 128M/s
        640M resilvered, 82.04% done, 00:00:01 to go
config:

        NAME                        STATE     READ WRITE CKSUM
        mypool                      DEGRADED     0     0     0
          mirror-0                  DEGRADED     0     0     0
            ada0p3                  ONLINE       0     0     0
            replacing-1             UNAVAIL      0     0     0
              15732067398082357289  UNAVAIL      0     0     0  was /dev/ada1p3/old
              ada2p3                ONLINE       0     0     0  (resilvering)

errors: No known data errors
# zpool status
  pool: mypool
 state: ONLINE
  scan: resilvered 781M in 00:00:17 with 0 errors on Sat Jul 11 14:52:38 2026
config:

        NAME        STATE     READ WRITE CKSUM
        mypool      ONLINE       0     0     0
          mirror-0  ONLINE       0     0     0
            ada0p3  ONLINE       0     0     0
            ada2p3  ONLINE       0     0     0

errors: No known data errors
```

## 23.3.11. 热备与 zfsd 自动替换

拥有冗余 vdev 的池可以注册 [hot spare](/handbook/di-23-zhang-z-wen-jian-xi-tong-zfs/23.10.-zfs-te-xing-he-shu-yu.md) 磁盘，作为待命设备替代故障设备。热备必须至少与其替代的设备一样大。在创建池时通过在 `spare` 关键字后列出热备来指定，如 `zpool create <mypool> mirror <ada0p3> <ada1p3> spare <ada3p3>`，或使用 `zpool add` 向现有池添加：

```sh
# zpool add mypool spare ada3p3
# zpool status
  pool: mypool
 state: ONLINE
config:

        NAME        STATE     READ WRITE CKSUM
        mypool      ONLINE       0     0     0
          mirror-0  ONLINE       0     0     0
            ada0p3  ONLINE       0     0     0
            ada1p3  ONLINE       0     0     0
        spares
          ada3p3    AVAIL

errors: No known data errors
```

热备保持空闲，显示为 `AVAIL`，直到有设备发生故障。使用 `zpool replace` 手动激活热备，指定故障设备与热备：

```sh
# zpool replace mypool ada1p3 ada3p3
# zpool status
  pool: mypool
 state: DEGRADED
status: One or more devices could not be opened.  Sufficient replicas exist for
        the pool to continue functioning in a degraded state.
action: Attach the missing device and online it using 'zpool online'.
   see: https://openzfs.github.io/openzfs-docs/msg/ZFS-8000-2Q
  scan: resilvered 781M in 00:00:21 with 0 errors on Sat Jul 11 09:14:33 2026
config:

        NAME          STATE     READ WRITE CKSUM
        mypool        DEGRADED     0     0     0
          mirror-0    DEGRADED     0     0     0
            ada0p3    ONLINE       0     0     0
            spare-1   DEGRADED     0     0     0
              ada1p3  UNAVAIL      0     0     0  cannot open
              ada3p3  ONLINE       0     0     0
        spares
          ada3p3      INUSE     currently in use

errors: No known data errors
```

热备替代在设计上是临时的，池会保持此状态直到管理员解决。在物理替换故障磁盘并使用 [zpool replace](#id-23.3.9.-ti-huan-zheng-chang-de-she-bei) 重同步新设备后，使用 `zpool detach <mypool> <ada3p3>` 让热备回到待命状态。若要将热备提升为 vdev 的永久成员，则使用 `zpool detach <mypool> <ada1p3>` 分离故障设备。

`autoreplace` 池属性默认关闭，控制当新磁盘出现在先前属于池的设备所在的同一物理位置时会发生什么。将 `autoreplace` 设置为 `on` 后，ZFS 会自动用新磁盘替换旧设备，无需 `zpool replace` 命令：

```sh
# zpool set autoreplace=on mypool
```

在 FreeBSD 上，对故障的自动响应（包括遵循 `autoreplace`）由 **zfsd(8)** 完成，这是基本系统中的 ZFS 故障管理守护进程。该守护进程默认未启用。使用以下命令启用并启动：

```sh
# sysrc zfsd_enable="YES"
# service zfsd start
```

**zfsd(8)** 监听池事件并执行以下操作：

* 当设备从冗余 vdev 中消失，或 vdev 进入 degraded 或 faulted 状态时，激活热备。
* 当 vdev 在 60 秒内产生超过 50 次 I/O 错误或超过 8 次延迟 I/O 操作时，将 vdev 标记为 faulted，然后激活热备。
* 当 vdev 在 60 秒内产生超过 50 次校验和错误时，将 vdev 标记为 degraded，然后激活热备。
* 当设备重新出现时，将其重新联机，并对其缺席期间写入的数据触发重同步。
* 当池设置了 `autoreplace=on` 时，用出现在同一物理位置的新磁盘替换缺失的设备。
* 永久替换设备的重同步完成后，将热备返回待命状态。

> **注意**
>
> FreeBSD 使用 **zfsd(8)** 进行故障管理。Linux OpenZFS 平台上的 ZFS Event Daemon（ZED）不是 FreeBSD 的一部分。

使用 `zpool events` 检查驱动这些决策的事件流。添加 `-v` 显示每个事件的完整载荷，`-f` 让命令持续运行，在新事件到达时打印。ZFS 也会将这些事件传递给 **devd(8)**。**/etc/devd/zfs.conf** 中的规则将事件记录到系统日志，并作为自定义操作的模板，例如在池进入 degraded 状态时发送邮件。

## 23.3.12. 对池进行 Scrub

建议定期对池运行 [scrub](/handbook/di-23-zhang-z-wen-jian-xi-tong-zfs/23.10.-zfs-te-xing-he-shu-yu.md)，最好每月至少一次。`scrub` 操作会消耗磁盘资源，因此在运行时会降低性能。请避免在高负载时期安排 `scrub` 操作，或者使用[调优](/handbook/di-23-zhang-z-wen-jian-xi-tong-zfs/23.8.-gao-ji-zhu-ti.md)中描述的 I/O 调度器可调参数降低其影响。

```sh
# zpool scrub mypool
# zpool status
  pool: mypool
 state: ONLINE
  scan: scrub in progress since Sat Jul 11 20:52:54 2026
        130G / 8.60T scanned at 649M/s, 116G / 8.60T issued at 580M/s
        0B repaired, 1.32% done, 04:15:41 to go
config:

        NAME        STATE     READ WRITE CKSUM
        mypool      ONLINE       0     0     0
          raidz2-0  ONLINE       0     0     0
            ada0p3  ONLINE       0     0     0
            ada1p3  ONLINE       0     0     0
            ada2p3  ONLINE       0     0     0
            ada3p3  ONLINE       0     0     0
            ada4p3  ONLINE       0     0     0
            ada5p3  ONLINE       0     0     0

errors: No known data errors
```

当运行中的 scrub 干扰其他工作时，使用 `zpool scrub -p <mypool>` 暂停它；再次运行 `zpool scrub <mypool>` 会从停止处恢复。要取消 scrub 操作，运行 `zpool scrub -s <mypool>`。`zpool scrub -w <mypool>` 会等待 scrub 完成才返回，这在脚本中很有用。当 scrub 报告错误后，`zpool scrub -e <mypool>` 执行 *错误 scrub*，只重新验证已知有错误的块，完成时间远短于完整 scrub。错误 scrub 需要 OpenZFS 2.2，首次发布于 FreeBSD 14.0。

**periodic(8)** 可以自动运行 scrub。要让 periodic 对上次 scrub 超过 35 天的每个池执行 scrub，在 **/etc/periodic.conf** 中添加此行：

```sh
daily_scrub_zfs_enable="YES"
```

设置 `daily_scrub_zfs_default_threshold="<days>"` 更改两次 scrub 之间的天数。**periodic.conf(5)** 还描述了每个池的阈值。设置 `daily_status_zfs_enable="YES"` 会将池健康检查添加到每日 **periodic(8)** 报告中。

## 23.3.13. 自我修复

存储在数据块中的校验和使文件系统可 *自我修复*。此功能会在检测到数据的校验和与存储池中其他设备记录的校验和不匹配时，自动修复数据。例如，一个镜像配置中有两块磁盘，其中一块磁盘开始出现故障，无法再正确存储数据。这种情况在长期存档存储中尤为严重，因为数据可能长时间未被访问。传统的文件系统需要运行命令来检查和修复数据，如 **fsck(8)**。这些命令需要时间，在严重情况下，管理员需要决定执行哪种修复操作。而 ZFS 在检测到数据块的校验和不匹配时，会尝试从镜像磁盘读取数据。如果该磁盘提供了正确的数据，ZFS 会将其提供给应用程序，并修复具有错误校验和的磁盘上的数据。此过程在正常池操作期间无需管理员干预。

以下示例展示了这种自我修复行为，创建由 **/dev/ada0p1** 和 **/dev/ada1p1** 组成的镜像池。

```sh
# zpool create healer mirror /dev/ada0p1 /dev/ada1p1
# zpool status healer
  pool: healer
 state: ONLINE
config:

    NAME        STATE     READ WRITE CKSUM
    healer      ONLINE       0     0     0
      mirror-0  ONLINE       0     0     0
       ada0p1   ONLINE       0     0     0
       ada1p1   ONLINE       0     0     0

errors: No known data errors
# zpool list
NAME     SIZE  ALLOC   FREE  CKPOINT  EXPANDSZ   FRAG    CAP  DEDUP    HEALTH  ALTROOT
healer   960M   111K   960M        -         -     0%     0%  1.00x    ONLINE  -
```

将一些重要数据复制到池中，利用自我修复功能保护数据免受错误，并创建池的校验和以供后续比较。

```sh
# cp /some/important/data /healer
# zpool list
NAME     SIZE  ALLOC   FREE  CKPOINT  EXPANDSZ   FRAG    CAP  DEDUP    HEALTH  ALTROOT
healer   960M  67.7M   892M        -         -     0%     7%  1.00x    ONLINE  -
# sha1 /healer > checksum.txt
# cat checksum.txt
SHA1 (/healer) = 2753eff56d77d9a536ece6694bf0a82740344d1f
```

通过向镜像中一块磁盘的开头写入随机数据来模拟数据损坏。为了防止 ZFS 在检测到损坏时修复数据，首先导出池，然后在损坏后重新导入。

> **警告**
>
> 这是个危险操作，可能会销毁重要数据，仅用于演示。**在正常操作的存储池中不要尝试**。不要在任何具有 ZFS 文件系统以外分区的磁盘上运行此有意损坏示例。不要使用池外的任何其他磁盘设备名。确保存在正确的池备份，并在运行命令之前测试它们！

```sh
# zpool export healer
# dd if=/dev/random of=/dev/ada1p1 bs=1m count=200
200+0 records in
200+0 records out
209715200 bytes transferred in 62.992162 secs (3329227 bytes/sec)
# zpool import healer
```

池的状态显示某个设备出现了错误。请注意，应用程序读取数据时未收到任何错误数据。ZFS 从未受影响的 `ada0p1` 镜像磁盘提供了数据。要查找校验和错误的设备，请查看 `CKSUM` 列包含非零值的设备。

```sh
# zpool status healer
  pool: healer
 state: ONLINE
status: One or more devices has experienced an unrecoverable error.  An
        attempt was made to correct the error.  Applications are unaffected.
action: Determine if the device needs to be replaced, and clear the errors
        using 'zpool clear' or replace the device with 'zpool replace'.
   see: https://openzfs.github.io/openzfs-docs/msg/ZFS-8000-9P
config:

    NAME        STATE     READ WRITE CKSUM
    healer      ONLINE       0     0     0
      mirror-0  ONLINE       0     0     0
       ada0p1   ONLINE       0     0     0
       ada1p1   ONLINE       0     0     1

errors: No known data errors
```

ZFS 检测到错误并通过使用未受影响的 `ada0p1` 镜像磁盘中的冗余数据修复。与原始校验和的比较将显示池是否再次一致。

```sh
# sha1 /healer >> checksum.txt
# cat checksum.txt
SHA1 (/healer) = 2753eff56d77d9a536ece6694bf0a82740344d1f
SHA1 (/healer) = 2753eff56d77d9a536ece6694bf0a82740344d1f
```

在有意破坏数据时，生成校验和并与池数据仍然一致。这展示了 ZFS 如何在校验和不同的情况下自动检测并修复任何错误。请注意，这只有在池中有足够的冗余时才可能。由单个设备组成的池没有自我修复能力。这也是为什么校验和在 ZFS 中如此重要；不要因任何原因禁用它们。ZFS 无需 **fsck(8)** 或类似的文件系统一致性检查程序来检测和修复这些问题，并在出现问题时保持池的可用性。现在需要 scrub 操作来覆盖 `ada1p1` 上的损坏数据。

```sh
# zpool scrub healer
# zpool status healer
  pool: healer
 state: ONLINE
status: One or more devices has experienced an unrecoverable error.  An
        attempt was made to correct the error.  Applications are unaffected.
action: Determine if the device needs to be replaced, and clear the errors
        using 'zpool clear' or replace the device with 'zpool replace'.
   see: https://openzfs.github.io/openzfs-docs/msg/ZFS-8000-9P
  scan: scrub in progress since Sat Jul 11 10:34:02 2026
        40.8M scanned at 20.4M/s, 24.9M issued at 12.4M/s, 67.0M total
        9.63M repaired, 37.16% done, 00:00:03 to go
config:

    NAME        STATE     READ WRITE CKSUM
    healer      ONLINE       0     0     0
      mirror-0  ONLINE       0     0     0
       ada0p1   ONLINE       0     0     0
       ada1p1   ONLINE       0     0   627  (repairing)

errors: No known data errors
```

scrub 操作从 `ada0p1` 读取数据，并在 `ada1p1` 上重写任何具有错误校验和的数据，显示为 `zpool status` 中的 `(repairing)` 输出。操作完成后，池状态将变为：

```sh
# zpool status healer
  pool: healer
 state: ONLINE
status: One or more devices has experienced an unrecoverable error.  An
        attempt was made to correct the error.  Applications are unaffected.
action: Determine if the device needs to be replaced, and clear the errors
        using 'zpool clear' or replace the device with 'zpool replace'.
   see: https://openzfs.github.io/openzfs-docs/msg/ZFS-8000-9P
  scan: scrub repaired 66.5M in 00:00:06 with 0 errors on Sat Jul 11 10:34:08 2026
config:

    NAME        STATE     READ WRITE CKSUM
    healer      ONLINE       0     0     0
      mirror-0  ONLINE       0     0     0
       ada0p1   ONLINE       0     0     0
       ada1p1   ONLINE       0     0 2.72K

errors: No known data errors
```

在 scrub 操作完成并将所有数据从 `ada0p1` 同步到 `ada1p1` 后，使用 `zpool clear` 清除池状态中的错误消息。

```sh
# zpool clear healer
# zpool status healer
  pool: healer
 state: ONLINE
  scan: scrub repaired 66.5M in 00:00:06 with 0 errors on Sat Jul 11 10:34:08 2026
config:

    NAME        STATE     READ WRITE CKSUM
    healer      ONLINE       0     0     0
      mirror-0  ONLINE       0     0     0
       ada0p1   ONLINE       0     0     0
       ada1p1   ONLINE       0     0     0

errors: No known data errors
```

池现在恢复到完全正常的状态，所有错误计数都为零。

## 23.3.14. TRIM 与初始化

固态硬盘和精简配置存储在 ZFS 通知其哪些块不再使用时性能最佳。`zpool trim` 将该信息传递给池中每个支持 TRIM 或 UNMAP 命令的设备：

```sh
# zpool trim mypool
```

在池名后指定设备名可以修剪单个设备，如 `zpool trim mypool nda0p3`。`zpool trim -w` 等待修剪完成，`-c` 取消进行中的修剪，`-s` 暂停修剪；再次运行 `zpool trim` 会恢复暂停的修剪。在支持的设备上，`zpool trim --secure` 请求安全 TRIM，设备保证擦除修剪块上存储的数据。

`zpool status -t` 显示每个设备的修剪进度：

```sh
# zpool status -t mypool
  pool: mypool
 state: ONLINE
  scan: scrub repaired 0B in 00:12:33 with 0 errors on Sat Jul 11 03:31:11 2026
config:

    NAME        STATE     READ WRITE CKSUM
    mypool      ONLINE       0     0     0
      mirror-0  ONLINE       0     0     0
        nda0p3  ONLINE       0     0     0  (23% trimmed, started at Sat Jul 11 09:15:04 2026)
        nda1p3  ONLINE       0     0     0  (22% trimmed, started at Sat Jul 11 09:15:04 2026)

errors: No known data errors
```

将 `autotrim` 池属性设置为 `on`，让 ZFS 在池释放空间时持续发出小的 TRIM 命令：

```sh
# zpool set autotrim=on mypool
```

自动修剪会跳过较小的已释放区域，并给设备带来持续的额外负载。对于大多数系统，保持 `autotrim` 关闭并按计划运行完整的 `zpool trim` 效果更好。在 FreeBSD 14.1 及更高版本上，当 **/etc/periodic.conf** 包含 `daily_trim_zfs_enable="YES"` 时，**periodic(8)** 会每日运行这样的修剪。

`zpool initialize` 是修剪的对应操作：它向指定设备的所有未分配空间写入模式，或在未指定设备名时向池中每个符合条件的设备写入。这会强制后端存储预先分配空间，避免精简配置虚拟磁盘上的首次写入延迟，并在信任新设备存储数据前对其进行演练。

```sh
# zpool initialize mypool
```

与修剪一样，`-c` 取消初始化，`-s` 暂停初始化，`-w` 等待初始化完成；`-u` 从设备上移除初始化状态。详情请参阅 **zpool-trim(8)** 和 **zpool-initialize(8)**。

## 23.3.15. 池检查点

`zpool checkpoint` 保存整个池的状态，包括每个数据集和池配置，使随后的回卷能将池恢复到创建检查点时的精确状态。在升级操作系统、启用新池特性或重组数据集等有风险的管理操作前创建检查点：

```sh
# zpool checkpoint mypool
```

一个池最多同时持有一个检查点。`zpool list` 的 `CKPOINT` 列显示检查点随着池偏离保存状态而消耗的空间：

```sh
# zpool list mypool
NAME     SIZE  ALLOC   FREE  CKPOINT  EXPANDSZ   FRAG    CAP  DEDUP    HEALTH  ALTROOT
mypool  4.50T  1.42T  3.08T     221M         -     4%    31%  1.00x    ONLINE  -
```

要回卷，导出池并使用 `--rewind-to-checkpoint` 再次导入：

```sh
# zpool export mypool
# zpool import --rewind-to-checkpoint mypool
```

回卷会丢弃创建检查点之后对池所做的所有更改，包括较新的快照和属性更改。丢弃不再需要的检查点以释放其占用的空间；`-w` 等待丢弃完成：

```sh
# zpool checkpoint -d -w mypool
```

存在检查点时，ZFS 拒绝更改池结构的操作：`zpool remove`、`zpool attach`、`zpool detach`、`zpool split` 和 `zpool reguid`。创建检查点后释放的空间在丢弃检查点前不会被回收，因此繁忙池上长期存在的检查点可能填满池。

> **注意**
>
> 检查点不能替代快照或备份。它只在短时间内防范管理失误，与池位于同一组磁盘上，回卷会丢弃创建检查点之后写入的所有内容。

详情请参阅 **zpool-checkpoint(8)**。

## 23.3.16. 扩展池

每个 vdev 中最小的设备限制了冗余池的可用大小。将最小设备替换为更大的设备。完成 [replace](#id-23.3.9.-ti-huan-zheng-chang-de-she-bei) 或 [resilver](/handbook/di-23-zhang-z-wen-jian-xi-tong-zfs/23.10.-zfs-te-xing-he-shu-yu.md) 操作后，池可以使用新设备的容量增长。例如，考虑由 1 TB 和 2 TB 硬盘组成的镜像池。可用空间为 1 TB。当将 1 TB 硬盘替换为另一个 2 TB 硬盘时，resilver 操作将现有数据复制到新硬盘。由于两个硬盘现在都具有 2 TB 的容量，因此镜像池的可用空间将增加到 2 TB。

默认情况下，池不会自动使用新容量。在替换设备前将 `autoexpand` 池属性设置为 `on`，池会在最后一块较小的设备离开 vdev 时立即增长：

```sh
# zpool set autoexpand=on mypool
```

否则，通过对每个设备使用 `zpool online -e` 开始扩展。扩展所有设备后，额外的空间将可供池使用。

要通过添加磁盘而非替换现有磁盘来扩展 RAID-Z vdev，请参阅 [RAID-Z 扩展](#id-23.3.4.-raid-z-kuo-zhan)。

## 23.3.17. 导入和导出池

在将池迁移到另一台系统之前，应先 *导出* 池。ZFS 会卸载所有数据集，并将每个设备标记为已导出，但仍会锁定以防止被其他磁盘使用。这使得池可以在其他支持 ZFS 的机器、操作系统甚至不同硬件架构上 *导入*（有一些注意事项，参见 **zpool(8)**）。当数据集有打开的文件时，使用 `zpool export -f` 强制导出池。使用此命令时需小心。数据集会被强制卸载，可能会导致应用程序在这些数据集上有打开文件时出现意外行为。

导出未使用的池：

```sh
# zpool export mypool
```

导入池会自动挂载数据集。如果不希望出现这种行为，可以使用 `zpool import -N` 来防止自动挂载。`zpool import -o` 可以为此次导入设置临时属性。`zpool import -o altroot=` 能使用基本挂载点而不是文件系统根目录导入池。如果池上次使用的是不同的系统，并且未正确导出，可以使用 `zpool import -f` 强制导入池。`zpool import -a` 导入所有未被其他系统使用的池。

**zpool-import(8)** 还提供了恢复损坏池的选项。`zpool import -F` 在最近的几个事务组损坏时尝试将池回卷到更早的事务组，丢弃最后几秒的写入。`zpool import -m` 允许导入缺少专用日志设备的池。`zpool import -o readonly=on` 以只读方式导入池，阻止所有写入，这在取证或从故障池抢救数据时很有用。`zpool import -R /mnt` 将 `altroot=/mnt` 与 `cachefile=none` 结合，使救援式导入不打乱运行中系统的挂载路径和池缓存。

列出所有可导入的池：

```sh
# zpool import
   pool: mypool
     id: 9930174748043525076
  state: ONLINE
 action: The pool can be imported using its name or numeric identifier.
 config:

        mypool    ONLINE
          ada0p1  ONLINE
```

使用替代根目录导入池：

```sh
# zpool import -o altroot=/mnt mypool
# zfs list
NAME                 USED  AVAIL  REFER  MOUNTPOINT
mypool               110K  47.0G    31K  /mnt/mypool
```

在引导时，由 **/etc/rc.conf** 中的 `zfs_enable="YES"` 启用的 ZFS 启动脚本会导入 **/etc/zfs/zpool.cache** 中记录的每个池。导入池会自动将其添加到该缓存文件；`cachefile` 池属性控制此行为。以 `cachefile=none` 导入的池在重启后不会自动返回。

### 23.3.17.1. 导入 GELI 加密池

FreeBSD 安装程序的“Encrypt Disks”选项使用 **geli(8)** 加密池的分区，详见“加密磁盘分区”一节，而非使用 ZFS 原生加密。在已安装的系统上，loader 会提示输入口令，并在挂载根池之前附加 provider，但 ZFS 本身对加密一无所知：从救援介质引导或将磁盘移动到另一台主机时，在附加 GELI provider 之前，`zpool import` 找不到池。

附加池中每块磁盘的加密 `freebsd-zfs` 分区（提供口令），然后导入池：

```sh
# geli attach ada0p4
Enter passphrase:
# zpool import -f -R /mnt zroot
```

使用 `gpart show` 标识 `freebsd-zfs` 分区；在默认安装程序布局中，加密分区为 `p4`。使用旧版布局安装的系统会保留一个单独的未加密引导池，并在该池上的 **/boot/encryption.key** 中存储密钥文件；使用 `geli attach -k /path/to/encryption.key` 附加这些 provider。

## 23.3.18. 升级存储池

升级 FreeBSD 后，或者从使用较旧版本的系统导入池时，需要手动升级池以启用新的磁盘上特性。在升级之前，考虑池是否可能在未来需要在旧系统上导入。升级是单向过程。可以升级旧池，但已启用新特性的池无法再降级。

池不再携带单一的版本号。每个磁盘上格式更改都是一个独立的 *特性标志*，详见 **zpool-features(7)**。当池允许使用某特性时，该特性被 *启用*；当池存储了依赖于此特性的数据时，该特性变为 *活动*。已启用但未活动的特性不影响兼容性。一旦特性变为活动，不支持该特性的软件将无法再导入池，不过所有活动特性都是“只读兼容”的池仍允许只读导入。

`zpool status` 会报告池上未启用的受支持特性：

```sh
# zpool status mypool
  pool: mypool
 state: ONLINE
status: Some supported and requested features are not enabled on the pool.
        The pool can still be used, but some features are unavailable.
action: Enable all features using 'zpool upgrade'. Once this is done,
        the pool may no longer be accessible by software that does not support
        the features. See zpool-features(7) for details.
  scan: scrub repaired 0B in 00:11:03 with 0 errors on Sat Jul 11 03:15:41 2026
config:

        NAME        STATE     READ WRITE CKSUM
        mypool      ONLINE       0     0     0
          mirror-0  ONLINE       0     0     0
            ada0p1  ONLINE       0     0     0
            ada1p1  ONLINE       0     0     0

errors: No known data errors
```

不带参数运行 `zpool upgrade` 会列出每个有未启用特性的池：

```sh
# zpool upgrade
This system supports ZFS pool feature flags.

Some supported features are not enabled on the following pools. Once a
feature is enabled the pool may become incompatible with software
that does not support the feature. See zpool-features(7) for details.

Note that the pool 'compatibility' feature can be used to inhibit
feature upgrades.

POOL  FEATURE
---------------
mypool
      zilsaxattr
      head_errlog
      blake3
      block_cloning
      vdev_zaps_v2
```

使用 `zpool upgrade -v` 列出运行系统支持的每个特性，以及旧式版本号。在池上启用所有受支持特性：

```sh
# zpool upgrade mypool
This system supports ZFS pool feature flags.

Enabled the following features on 'mypool':
  zilsaxattr
  head_errlog
  blake3
  block_cloning
  vdev_zaps_v2
```

对于必须能在运行较旧 ZFS 软件的系统上导入的池，可以通过 `compatibility` 池属性限制 `zpool create` 和 `zpool upgrade` 启用的特性：

```sh
# zpool create -o compatibility=openzfs-2.1-freebsd mypool mirror /dev/ada0p1 /dev/ada1p1
```

使用 `zpool set` 在现有池上设置该属性同样有效。每个命名的特性集对应 **/usr/share/zfs/compatibility.d** 中的一个文件，默认值 `off` 允许所有特性。设置该属性不会禁用已启用的特性。

> **警告**
>
> 在从池引导的系统上更新引导代码，以支持新的池特性。在包含引导代码的分区上使用 `gpart bootcode`。根据系统引导方式的不同，有两种类型的引导代码可用：GPT（最常见的选项）和 EFI（用于较新的系统）。
>
> 对于使用 GPT 引导的旧系统，可以使用以下命令：
>
> ```sh
> # gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 ada1
> ```
>
> 对于使用 EFI 引导的系统，执行以下命令：
>
> ```sh
> # mount -t msdosfs /dev/ada1p1 /boot/efi
> # cp /boot/loader.efi /boot/efi/efi/boot/BOOTX64.efi
> # cp /boot/loader.efi /boot/efi/efi/freebsd/loader.efi
> ```
>
> 这些说明适用于 amd64 系统。根据架构不同，文件名会有所不同。请参阅 **uefi(8)** 以查找特定架构的文件名。
>
> 将引导代码应用于池中的所有可引导磁盘。有关更多信息，请参阅 **gpart(8)**。

## 23.3.19. 显示记录的池历史

ZFS 会记录所有改变池状态的命令，包括创建数据集、更改属性或替换磁盘。回顾池的创建历史很有用，同样也可以检查哪个用户在什么时候执行了特定的操作。历史记录并不保存在日志文件中，而是池的一部分。查看历史记录的命令正如其名为 `zpool history`：

```sh
# zpool history
History for 'tank':
2026-07-11.10:24:05 zpool create tank mirror /dev/ada0p1 /dev/ada1p1
2026-07-11.18:50:58 zfs set atime=off tank
2026-07-11.18:51:09 zfs set checksum=fletcher4 tank
2026-07-11.18:51:18 zfs create tank/backup
```

输出显示了 `zpool` 和 `zfs` 命令如何以时间戳记录改变池状态的操作。像 `zfs list` 这样的命令不会包含在内。若不指定池名称，ZFS 会显示所有池的历史记录。

通过提供选项 `-i` 或 `-l`，`zpool history` 可以显示更多信息。`-i` 会显示用户发起的事件以及内部记录的 ZFS 事件。

```sh
# zpool history -i
History for 'tank':
2026-07-11.10:24:05 [txg:5] create pool version 5000; software version zfs-2.2.7-FreeBSD_gd75f9ee8b; uts myzfsbox 14.3-RELEASE 1403000 amd64
2026-07-11.18:50:53 [txg:50] set tank (21) atime=0
2026-07-11.18:50:58 zfs set atime=off tank
2026-07-11.18:51:04 [txg:53] set tank (21) checksum=7
2026-07-11.18:51:09 zfs set checksum=fletcher4 tank
2026-07-11.18:51:13 [txg:55] create tank/backup (39)
2026-07-11.18:51:18 zfs create tank/backup
```

通过加上 `-l` 显示更多细节。长格式的历史记录包括了执行命令的用户和命令发生的主机名信息。

```sh
# zpool history -l
History for 'tank':
2026-07-11.10:24:05 zpool create tank mirror /dev/ada0p1 /dev/ada1p1 [user 0 (root) on myzfsbox:global]
2026-07-11.18:50:58 zfs set atime=off tank [user 0 (root) on myzfsbox:global]
2026-07-11.18:51:09 zfs set checksum=fletcher4 tank [user 0 (root) on myzfsbox:global]
2026-07-11.18:51:18 zfs create tank/backup [user 0 (root) on myzfsbox:global]
```

输出显示 `root` 用户创建了由 **/dev/ada0p1** 和 **/dev/ada1p1** 组成的镜像池。主机名 `myzfsbox` 也在每条命令中显示。当池从一个系统导出并导入到另一个系统时，主机名信息变得非常重要。可以通过每条命令记录的主机名区分在其他系统上执行的命令。

将两个选项结合使用，`zpool history` 可以提供任何池的最详细信息。池历史记录在追踪执行的操作或调试时提供了宝贵的帮助。

## 23.3.20. 性能监控

ZFS 提供了内建的监控系统，可以实时显示池的 I/O 统计数据。它展示了池的已用空间和空闲空间、每秒读写操作以及使用的 I/O 带宽。默认情况下，ZFS 会监控并显示系统中所有池的状态。若只想监控某个特定池，可以指定池的名称。以下是基本示例：

```sh
# zpool iostat
               capacity     operations    bandwidth
pool        alloc   free   read  write   read  write
----------  -----  -----  -----  -----  -----  -----
data         288G  1.53T      2     11  11.3K  57.1K
```

要持续查看 I/O 活动，可以指定一个数字作为最后一个参数，表示每次更新的间隔时间（以秒为单位）。每次统计数据将会在该间隔后打印一次。按 `Ctrl+C` 停止连续监控。如果还要指定显示的统计次数，可以在命令行中添加第二个数字。

使用 `-v` 显示更详细的 I/O 统计数据。每个池中的设备都会有一行统计数据。这有助于查看每个设备的读写操作，帮助判断是否有某个设备拖慢了池的性能。以下是镜像池的例子，包含两个设备：

```sh
# zpool iostat -v
                            capacity     operations    bandwidth
pool                     alloc   free   read  write   read  write
-----------------------  -----  -----  -----  -----  -----  -----
data                      288G  1.53T      2     12  9.23K  61.5K
  mirror                  288G  1.53T      2     12  9.23K  61.5K
    ada1p1                   -      -      0      4  5.61K  61.7K
    ada2p1                   -      -      1      4  5.04K  61.7K
-----------------------  -----  -----  -----  -----  -----  -----
```

`zpool iostat` 提供了对 I/O 管线更深入的几种视图。`-l` 增加平均延迟列，将总等待时间拆分为磁盘时间和在各类 I/O 队列中花费的时间。`-q` 显示每个 vdev 队列中挂起和活跃的操作数。`-w` 打印完整的延迟直方图，`-r` 打印每个叶子 vdev 的请求大小直方图。

`-l` 的延迟列让用户能轻松找出拖慢整个 vdev 的单块慢磁盘：

```sh
# zpool iostat -lv data
              capacity     operations     bandwidth    total_wait     disk_wait    syncq_wait    asyncq_wait  scrub   trim  rebuild
pool        alloc   free   read  write   read  write   read  write   read  write   read  write   read  write   wait   wait     wait
----------  -----  -----  -----  -----  -----  -----  -----  -----  -----  -----  -----  -----  -----  -----  -----  -----  -------
data         288G  1.53T    156    212  19.4M  26.6M   14ms  186ms    5ms  184ms    1us    2us    8ms    2ms      -      -        -
  mirror-0   288G  1.53T    156    212  19.4M  26.6M   14ms  186ms    5ms  184ms    1us    2us    8ms    2ms      -      -        -
    ada1p1      -      -     79    106   9.7M  13.3M    3ms    5ms    3ms    4ms    1us    2us    1ms    1ms      -      -        -
    ada2p1      -      -     77    106   9.7M  13.3M  212ms  187ms  208ms  183ms    1us    2us   15ms    3ms      -      -        -
----------  -----  -----  -----  -----  -----  -----  -----  -----  -----  -----  -----  -----  -----  -----  -----  -----  -------
```

在此示例中，`ada2p1` 完成其镜像伙伴 `ada1p1` 在个位数毫秒内完成的 I/O 需要数百毫秒的磁盘时间，而两者处理的操作数相近。镜像写入只有在最慢的成员完成后才完成，因此整个 vdev 的写入延迟跟随 `ada2p1`。在 `zpool status` 中没有读取、写入或校验和错误的情况下，正常运行时的高延迟计数通常表明磁盘在内部重试，是替换的候选对象。

必须等待后台池活动完成的脚本可以阻塞在 `zpool wait` 上：

```sh
# zpool wait -t scrub,resilver mypool
```

当指定的活动（如 `scrub`、`resilver`、`trim` 或 `remove`）都不在进行时，命令返回。完整的活动列表请参阅 **zpool-wait(8)**。

> **注意**
>
> `zpool status`、`zpool list`、`zpool get` 和 `zfs list` 接受 `-j` 生成 JSON 输出，对脚本解析而言比人类可读的表格更稳健。JSON 输出需要 OpenZFS 2.3 或更高版本，首次出现在 FreeBSD 15.0 中。

## 23.3.21. 拆分存储池

ZFS 可以将由一个或多个镜像 vdev 组成的池拆分成两个池。除非特别指定，ZFS 会从每个镜像中分离出最后一个成员，并创建包含相同数据的新池。在实际执行前，最好先使用 `-n` 选项做模拟运行，这会显示请求操作的细节，而不会实际执行该操作。这有助于确认操作会按照预期执行。


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://book.bsdcn.org/handbook/di-23-zhang-z-wen-jian-xi-tong-zfs/23.3.-zpool-guan-li.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
