Java 断电时原子文件移动复制文件
Java atomic file move duplicates files on power loss
Java 应用程序按以下方式移动原子文件:
Path source = Paths.get(fullFileName + ".tmp");
Path target = Paths.get(fullFileName);
Files.delete(target);
Files.move(source, target, StandardCopyOption.ATOMIC_MOVE);
源文件存在或在移动前被创建。
源和目标位于同一位置,因此具有相同的 FileSystemProvider
。
使用原子移动选项,我希望在任何给定时刻系统中只存在一个文件或抛出异常。
然而,当发生断电时,我发现驱动器上的源文件和目标文件具有相同的内容。
我不排除其他潜在问题,但到目前为止它一直可靠地留下重复项。
File system: EXT4
Storage type: eMMC Flash
CPU Architecture: ARM
OS: Debian 4.9.11-02300-ga1ac172-dirty #2 SMP PREEMPT Mon Apr 23 12:58:56 CDT 2018 armv7l GNU/Linux
我错过了什么吗?
这是否意味着不支持原子移动?
我认为您误解了什么是原子移动:
- 只有移动是原子的。其余的文件处理不是。
- POSIX 原子性保证是针对正常运行的软件,而不是断电情况。
考虑您的代码:
void foo(String fullFileName) {
// 1
Path source = Paths.get(fullFileName + ".tmp");
// 2
Path target = Paths.get(fullFileName);
// 3
Files.delete(target);
// 4
Files.move(source, target, StandardCopyOption.ATOMIC_MOVE);
// 5
}
如果程序在 1、2 或 3 处中断,那么您将这两个文件都留在系统中。你的原子移动还没有被调用,所以在那里移动不会影响任何东西。
如果程序在 4 或 5 时中断,您将只有一个文件,但如果电源中断,则文件系统恢复时的状态将不再有任何保证。
听起来你想要的是一个支持事务的数据库。
Java 应用程序按以下方式移动原子文件:
Path source = Paths.get(fullFileName + ".tmp");
Path target = Paths.get(fullFileName);
Files.delete(target);
Files.move(source, target, StandardCopyOption.ATOMIC_MOVE);
源文件存在或在移动前被创建。
源和目标位于同一位置,因此具有相同的 FileSystemProvider
。
使用原子移动选项,我希望在任何给定时刻系统中只存在一个文件或抛出异常。
然而,当发生断电时,我发现驱动器上的源文件和目标文件具有相同的内容。 我不排除其他潜在问题,但到目前为止它一直可靠地留下重复项。
File system: EXT4
Storage type: eMMC Flash
CPU Architecture: ARM
OS: Debian 4.9.11-02300-ga1ac172-dirty #2 SMP PREEMPT Mon Apr 23 12:58:56 CDT 2018 armv7l GNU/Linux
我错过了什么吗? 这是否意味着不支持原子移动?
我认为您误解了什么是原子移动:
- 只有移动是原子的。其余的文件处理不是。
- POSIX 原子性保证是针对正常运行的软件,而不是断电情况。
考虑您的代码:
void foo(String fullFileName) {
// 1
Path source = Paths.get(fullFileName + ".tmp");
// 2
Path target = Paths.get(fullFileName);
// 3
Files.delete(target);
// 4
Files.move(source, target, StandardCopyOption.ATOMIC_MOVE);
// 5
}
如果程序在 1、2 或 3 处中断,那么您将这两个文件都留在系统中。你的原子移动还没有被调用,所以在那里移动不会影响任何东西。
如果程序在 4 或 5 时中断,您将只有一个文件,但如果电源中断,则文件系统恢复时的状态将不再有任何保证。
听起来你想要的是一个支持事务的数据库。