已澄清的问题:
当操作系统发送将扇区写入磁盘的命令时,它是原子的吗?即,如果电源在写入命令之后立即发生故障,则新数据的写入完全成功,或者旧数据保持不变。我不关心在多个扇区写入时会发生什么-撕裂的页面是可以接受的。
老问题:
假设你在磁盘上有旧数据X,你在上面写了新数据Y,在写的过程中,一棵树倒在了电源线上。没有花哨的UPS或电池后备的磁盘控制器,你可能最终会得到一个撕裂的页面,其中磁盘上的数据是部分X和部分Y。你会最终出现磁盘上的数据是部分X,部分Y和部分垃圾的情况吗?
我一直在尝试理解ACID系统的设计,比如数据库,而我天真的想法是,firebird似乎不使用预写日志,它依赖于给定的写入不会破坏旧数据(X) -只是无法完全写入新数据(Y)。这意味着,如果X的一部分被覆盖,那么只能更改X中被覆盖的部分,而不能更改我们打算保留的X部分。
为了澄清,这意味着如果你有一个页面大小的缓冲区,比方说4096字节,填满了我们想要保留的一半Y,一半X -我们告诉操作系统在X上写这个缓冲区,除了严重的磁盘故障之外,我们想要保留的一半X在写入过程中被破坏。
发布于 2010-01-06 06:15:50
我认为页面撕裂不是问题所在。据我所知,所有驱动器都有足够的电力存储,以便在断电时完成当前扇区的写入。
问题是每个人都在说谎。
至少当数据库知道事务何时提交到磁盘时,每个人都在说谎。数据库发出fsync,操作系统仅在所有未完成的写操作都已提交到磁盘时才返回,对吧?也许不是。这是很常见的,特别是对于RAID卡和/或SATA驱动器,您的程序被告知一切都已提交(即fsync返回),但驱动器上还没有数据。
您可以尝试使用Brad's diskchecker来了解您将要用于数据库的平台是否能够在不丢失数据的情况下继续运行。底线:如果diskchecker失败,那么运行数据库的平台就不安全。使用ACID的数据库依赖于知道事务何时已提交到后备存储,以及何时未提交。无论数据库是否使用预写日志记录(如果数据库在没有执行fsync的情况下返回给用户,那么事务可能在失败的情况下丢失,因此它不应该声称它提供ACID语义),都是如此。
有一个讨论持久性的long thread on the Postgresql邮件列表。它从谈论固态硬盘开始,然后进入SATA驱动器、SCSI驱动器和文件系统。你可能会惊讶地发现你的数据有多容易丢失。对于需要持久性的数据库的任何人来说,这是一个很好的线程,而不仅仅是那些运行Postgresql的人。
发布于 2010-01-15 08:29:48
在这个问题上似乎没有人达成一致。所以我花了很多时间尝试不同的谷歌查询,直到我最终找到了答案。
来自RedHat员工、linux内核文件系统和虚拟内存开发人员Stephen Tweedie博士关于ext3 (他开发的) transcript here的演讲。如果有人知道,那一定是他。
“仅仅把东西写到日志中是不够的,因为日志中必须有一些标记,上面写着:嗯,(实际上有这个日志记录)这个日志记录实际上代表了磁盘的完整一致性吗?做到这一点的方法是通过一些原子操作,将该事务标记为在磁盘上已完成。”23m,14s
“现在,磁盘实际上提供了这些保证。如果您开始对磁盘执行写操作,那么即使在该扇区写入过程中断电,该磁盘也有足够的功率可用,它实际上可以从主轴的旋转能量中窃取能量;它有足够的功率来完成正在写入的扇区的写入。在所有情况下,磁盘都会提供保证。”23m,41s
发布于 2010-01-14 13:21:23
不,他们不是。更糟糕的是,在默认设置下,磁盘可能会说谎,并声称数据实际上在磁盘缓存中。出于性能方面的原因,这可能是可取的(实际耐用性会降低一个数量级),但这意味着如果您断电并且磁盘缓存没有物理写入,您的数据就会消失。
不幸的是,真正的持久性既难又慢,因为每次写入至少需要一次完整的旋转,或者使用日志记录/撤消进行2+。这限制了您每秒只能处理几百个DB事务,并且需要在相当低的级别上禁用写缓存。
然而,出于实际目的,在大多数情况下,差异并不是那么大。
请参见:
https://stackoverflow.com/questions/2009063
复制相似问题