Skip to content

实验记录:拔盘对 APFS 卷与磁盘映像的影响 ​

本文是一次受控实验的原始记录,用来回答挂载迁移选后端时的一个问题:

把容器数据放在外置盘的 APFS 卷里,和放在外置盘上的 APFS 磁盘映像(sparsebundle)里,写入过程中直接拔盘,各自会丢多少?

结论是磁盘映像在两轮测试中都整卷报废,APFS 卷只丢最后几个事务。面向用户的解释见为什么外置盘必须是 APFS。

环境 ​

项目值
系统macOS 27.0 (26A428),arm64
测试盘64 GB USB 闪存盘(U352),diskutil eraseDisk APFS APTEST GPT 后使用
APFS 卷在测试盘的 APFS 容器里 diskutil apfs addVolume 新建,diskutil mount -mountPoint ~/appports-test/usb-apfsmnt
磁盘映像hdiutil create -type SPARSEBUNDLE -fs APFS -size 20g,存放在测试盘根目录,hdiutil attach -mountpoint ~/appports-test/usb-imgmnt -nobrowse
写入负载Python 脚本:SQLite synchronous=FULL + WAL,循环插入并逐条提交,同时每 50 次提交写一个 64 KB 文件;每次提交写一行 committed N 到日志
拔盘方式直接拔出 USB 接口,不弹出
日期2026-09-19

第一轮:普通 fsync ​

两个写入进程并行 12 秒后拔盘。

拔前最后一次提交插回后
APFS 卷7177yank.db 报 database disk image is malformed;sqlite3 .recover 救回 7172 行,max(id)=7172;50 个文件全部在
磁盘映像25574hdiutil attach 报"无可装载的文件系统";fsck_apfs 报 container superblock is invalid;band 0 文件只有 3.26 MB(正常应为 8 MB)

映像的提交数是卷的三倍多,说明它的写入基本停留在宿主的页缓存里,并没有落盘。

第二轮:F_FULLFSYNC ​

写入脚本加上 pragma fullfsync=1; pragma checkpoint_fullfsync=1,这是 SQLite 在 macOS 上真正强制写穿到介质的方式(多数应用不开)。两边都慢了很多。

拔前最后一次提交插回后
APFS 卷1906integrity_check = ok,1905 行,max(id)=1905
磁盘映像373仍然无法挂载,超级块无效

即使应用层做到了最严格的落盘,映像内部 APFS 的检查点区域(落在 band 0)仍然处于半写状态。

第三轮:ASIF(已中止) ​

macOS 26 起提供单文件稀疏映像 ASIF(diskutil image create blank --format ASIF)。挂载后写入 12 秒、8000 次提交,尚未拔盘时决定中止:ASIF 只在 26+ 可用,对目标用户(12 至 26)没有意义,且它和 APFS 卷一样要求宿主是 APFS,解决不了 exFAT 的问题。

性能对照(拔盘前,同一块 U 盘) ​

负载内置 SSDAPFS 卷sparsebundle(宿主 APFS)sparsebundle(宿主 exFAT 映像)直接写 exFAT
SQLite 2000 次逐条提交0.07 s0.35 s0.10 s0.17 s1.69 s
2000 个 4 KB 小文件0.08 s0.10 s0.08 s0.09 s0.76 s
顺序写 256 MB + fsync0.07 s0.31 s0.37 s0.67 s0.80 s

映像的数据库提交比 APFS 卷还快,正是因为它没有真正落盘。exFAT 那一列说明就算能在 exFAT 上直接放数据库,性能也不适合聊天记录这类负载。

其它观察 ​

  • 映像方案不触发「可移动宗卷」TCC 授权:系统自带的便签(平台应用)在 APFS 卷上被静默拒绝,在映像上正常读写,日志没有任何 deny。
  • 映像删除文件后空间不归还,5 GB 写入并删除后映像仍占 5.6 GB,需要 hdiutil compact。
  • 拔盘后测试盘的两个 APFS 卷本身 fsck_apfs 均正常,损坏只发生在映像内部。

结论 ​

APFS 卷磁盘映像
拔盘丢失范围最后几个事务,数据库可修复整卷
外置盘格式必须 APFS任意
TCC 授权框首次一次无
性能原生相当(因未落盘)

AppPorts 因此只提供 APFS 卷后端。映像方案的其它优点不足以抵消"拔一次盘整卷消失"。

清理 ​

写入进程已停止,映像与测试卷已删除,~/appports-test/ 已删除,用作对照的便签容器数据已原样恢复。测试盘保留为空的 APFS 盘。

最近更新