当前位置: 首页 > Linux

系统掉电导致文件出现空符号(^@)问题的解决方法

时间:2023-04-06 01:20:51 Linux

我们的前端数据采集系统使用的是树莓派,树莓派运行基于Debian的Linux操作系统,文件系统格式为EXT4.发现收集的日志文件末尾偶尔会出现大量的^@。经过一番排查,发现是系统突然断电造成的。然后google了一下,说修改后文件的元数据变大了,但是实际数据因为断电没有写入硬盘,所以会用空符号(^@)填充。然后想了很多办法修复掉电后产生的异常数据(之前我们盒子加了自动重启线解决操作系统卡死的问题,每隔3天自动重启),没有问题。很好的解决办法,直到在极客时间的Linux运行中听说了文件系统的journal模式,经过一番查找,终于明白了这个问题的原理,找到了解决办法。EXT4是一种日志文件系统,它使用了类似MySQL中Transaction的概念来保??证一致性,将对文件的操作看成一个事务,同样采用了先写redolog的机制。分为以下三种模式(可以使用dmesg|grepEXT4查看:mountedfilesystemwithordereddatamode.opts:(null))journal首先将数据和元数据写入日志文件并放到磁盘上,commits日志文件,然后将数据和元数据写入硬盘正确位置(In-placewrite),异步删除已经写入硬盘正确位置的日志文件数据。如果发生系统崩溃,可以恢复重放日志文件中已提交的数据。这种方式最安全,但是性能较差(除了需要同时写入和读取数据),因为数据写入了两次。流程如下:ordered(默认)只有元数据写入日志文件,但保证数据先写入硬盘,再提交日志文件。流程图如下(步骤1和2可以同时进行,只要在步骤3之前完成即可):如果系统崩溃,可以通过重放日志文件恢复元数据,保证一致性文件系统,如果存储的数据是复用现有的文件块来存储数据,可以保证数据已经放在磁盘上,但是由于DelayedAllocation机制的存在,如果文件需要分配一个新的block写入,系统会延迟近1分钟才真正刷入硬盘,这会导致数据丢失,这就是为什么你在文件中看到^@来填充真实数据的原因。“延迟分配”意味着文件系统试图尽可能长时间地延迟为写入数据分配物理磁盘块。该策略带来了一些重要的性能优势。许多文件都是短暂的;延迟分配可以防止系统将稍纵即逝的临时文件写入磁盘。而且,对于寿命较长的文件,延迟分配允许内核积累更多数据并为数据连续分配块,从而加快该数据的写入和任何后续读取。这是在大多数现代文件系统中发现的重要优化。但是,如果没有为文件分配块,则没有必要将它们作为安全措施快速写入。由于这些块尚不存在,因此无法从中读取其他人的数据。所以ext4不会(不能)将未分配的块写出作为下一个日志提交周期的一部分。相反,这些块将等到内核d那时,物理块将被分配到磁盘上,数据将被持久化。内核不喜欢让文件数据未写入的时间太长,但仍可能需要一分钟左右(使用默认设置)刷新该数据-远远超过ext3通常看到的五秒。这就是为什么在使用ext4时崩溃会导致丢失相当多的数据。writeback仅元数据写入日志文件,但无法保证数据何时写入硬盘。有可能系统重启后元数据会恢复,但是数据会因为没有写入硬盘而丢失。流程图如下:最后挂载时将文件系统设置为journal模式,用性能换取强一致性。修改/etc/fstab:/dev/mapper/sd03/pi/ext4defaults,data=journal00ext4anddataloss