有没有办法在SSD上写入,如果在写入过程中断开连接,数据不会丢失?
Is there a way to write on a SSD, such that if it is disconnected during the writing process, no data is lost?
我有一个 Python 脚本,可以在外部 SSD 上记录摄像机的运动。计算机(Raspberry Pi)很有可能受到冲击并与驱动器断开连接(甚至与它的电源断开连接,但这是另一个话题,对吗?),但我不想丢失任何数据发生。可以实现吗?
我了解到,当驱动器未安全弹出时,只会丢失最后一个写入周期。写周期到底是什么?我如何使用它来完成我想要的?也许我可以写 5 秒的块(写周期为 5 秒),这样如果 SSD 断开连接,只会丢失 5 秒,你怎么看?
这在代码方面如何应用?
现在我正在使用 Picamera 库,它使用文件流。如果 SSD 断开连接,没有足够的时间 close()
流,这就是数据丢失的原因吗?在我的测试中,当我断开 SSD 连接时,无论我录制的序列是 1 分钟还是 15 秒长,我似乎只能看到视频的前 2-3 秒。
断开 SSD 后,我通常会在控制台中收到一些内核错误消息 (Linux):
Message from syslogd@raspberrypi at Nov 12 01:43:41 ...
kernel:[ 138.263099] Internal error: Oops: 5 [#1] PREEMPT SMP ARM
Message from syslogd@raspberrypi at Nov 12 01:43:41 ...
kernel:[ 138.366239] Process vc.ril.video_en (pid: 2403, stack limit = 0xb47c0210)
Message from syslogd@raspberrypi at Nov 12 01:43:41 ...
kernel:[ 138.374211] Stack: (0xb47c1c80 to 0xb47c2000)
Message from syslogd@raspberrypi at Nov 12 01:43:41 ...\
kernel:[ 138.379835] 1c80: 00000000 b5b84ce0 807fd650 b667536c a0000013 00000000 b47c1ccc b47c1ca8\
...
这会冻结此控制台会话中的所有内容。
有时,但很少见(大约 1/10 次),内核不会给出错误,但脚本会引发异常 (IOError: [Errno 5] Input/output error
) 并在控制台中显示堆栈跟踪。
如有任何见解,我们将不胜感激!
干杯!
当您的应用程序调用 "write()" 时,Linux 实际上并未写入磁盘。 (如果这样做,一切都会很慢。)
原因是磁盘在 "seeking" 时非常慢(绕磁盘移动),但在 "streaming" 时非常快(顺序写入数据)。所以 Linux 将在内存中缓冲数据,然后以大的顺序块将其全部写出。
默认情况下,Linux 会将数据在写出之前在内存中保留最多 30 秒。如果这对你来说太大了,你可以调整它。尝试 echo 500 > /proc/sys/vm/dirty_expire_centiseconds
尝试每 5 秒写出一次数据。
参见:
http://www.westnet.com/~gsmith/content/linux-pdflush.htm
https://lonesysadmin.net/2013/12/22/better-linux-disk-caching-performance-vm-dirty_ratio/
所以这就是我所做的,以确保只丢失非常少量的数据。
- 通过将 0 传递给
open
方法的 buffering
参数来关闭文件对象的缓冲模式(仅在以二进制模式打开文件时有效。例如 open(fileName, 'wb+', 0)
) .您还可以手动调用 flush
以在 write
. 之后清空文件缓冲区
- 正如@Evan 所指出的,定期调用
sync
或fsync
以强制将数据写入磁盘。 fsync() 或 sync() 之前的任何 write() 调用都将在同步调用 returns 之前发送到磁盘。性能会受到影响,可能会非常大。
我有一个 Python 脚本,可以在外部 SSD 上记录摄像机的运动。计算机(Raspberry Pi)很有可能受到冲击并与驱动器断开连接(甚至与它的电源断开连接,但这是另一个话题,对吗?),但我不想丢失任何数据发生。可以实现吗?
我了解到,当驱动器未安全弹出时,只会丢失最后一个写入周期。写周期到底是什么?我如何使用它来完成我想要的?也许我可以写 5 秒的块(写周期为 5 秒),这样如果 SSD 断开连接,只会丢失 5 秒,你怎么看?
这在代码方面如何应用?
现在我正在使用 Picamera 库,它使用文件流。如果 SSD 断开连接,没有足够的时间 close()
流,这就是数据丢失的原因吗?在我的测试中,当我断开 SSD 连接时,无论我录制的序列是 1 分钟还是 15 秒长,我似乎只能看到视频的前 2-3 秒。
断开 SSD 后,我通常会在控制台中收到一些内核错误消息 (Linux):
Message from syslogd@raspberrypi at Nov 12 01:43:41 ...
kernel:[ 138.263099] Internal error: Oops: 5 [#1] PREEMPT SMP ARM
Message from syslogd@raspberrypi at Nov 12 01:43:41 ...
kernel:[ 138.366239] Process vc.ril.video_en (pid: 2403, stack limit = 0xb47c0210)
Message from syslogd@raspberrypi at Nov 12 01:43:41 ...
kernel:[ 138.374211] Stack: (0xb47c1c80 to 0xb47c2000)
Message from syslogd@raspberrypi at Nov 12 01:43:41 ...\
kernel:[ 138.379835] 1c80: 00000000 b5b84ce0 807fd650 b667536c a0000013 00000000 b47c1ccc b47c1ca8\
...
这会冻结此控制台会话中的所有内容。
有时,但很少见(大约 1/10 次),内核不会给出错误,但脚本会引发异常 (IOError: [Errno 5] Input/output error
) 并在控制台中显示堆栈跟踪。
如有任何见解,我们将不胜感激!
干杯!
当您的应用程序调用 "write()" 时,Linux 实际上并未写入磁盘。 (如果这样做,一切都会很慢。)
原因是磁盘在 "seeking" 时非常慢(绕磁盘移动),但在 "streaming" 时非常快(顺序写入数据)。所以 Linux 将在内存中缓冲数据,然后以大的顺序块将其全部写出。
默认情况下,Linux 会将数据在写出之前在内存中保留最多 30 秒。如果这对你来说太大了,你可以调整它。尝试 echo 500 > /proc/sys/vm/dirty_expire_centiseconds
尝试每 5 秒写出一次数据。
参见: http://www.westnet.com/~gsmith/content/linux-pdflush.htm https://lonesysadmin.net/2013/12/22/better-linux-disk-caching-performance-vm-dirty_ratio/
所以这就是我所做的,以确保只丢失非常少量的数据。
- 通过将 0 传递给
open
方法的buffering
参数来关闭文件对象的缓冲模式(仅在以二进制模式打开文件时有效。例如open(fileName, 'wb+', 0)
) .您还可以手动调用flush
以在write
. 之后清空文件缓冲区
- 正如@Evan 所指出的,定期调用
sync
或fsync
以强制将数据写入磁盘。 fsync() 或 sync() 之前的任何 write() 调用都将在同步调用 returns 之前发送到磁盘。性能会受到影响,可能会非常大。