磁盘扇区写道原子吗?

2021-04-08 00:33:22

当OS发送命令将扇区写入磁盘时是它的原子?即,写入新数据成功完全或旧数据完好无损,如果在WRITE命令之后立即失败。我不关心多个扇区写入中发生的事情 - 撕裂页面是可接受的。

假设您在磁盘上有旧数据X,您可以在其上写下新数据y,并且在该写入过程中将树落在电源线上。没有花哨的UPS或电池备份磁盘控制器,最终可以使用撕裂的页面,其中磁盘上的数据是X部分x和部分Y.您可以结束磁盘上的数据是X的数据,部分Y和垃圾分开?

I'一直在试图理解像数据库ACID系统的设计,并天真的以为,似乎火鸟,它不使用预写日志,是靠着一个给定的写操作不会破坏旧的数据(X ) - 只能完全写入新数据(y)。这意味着如果X的一部分被覆盖,则只能更改被覆盖的X的一部分,而不是我们打算保留的X的一部分。

为了澄清,这意味着如果您有一个页面大小的缓冲区,请说出4096字节,充满了一半y,我们想要保留的半x - 并且我们告诉操作系统将缓冲区写在x上,严重磁盘没有缺点在写入期间,我们想要保留的半x会失败。

2我会说最糟糕的是,头部从撞击的树上振动足够的震动,以将头部首先滑入脆弱的陶瓷盘子,导致它粉碎成一百万件。它以前发生了它。 - Blueraja - Danny Pflughoeft

是的,这将是非常糟糕的。 '据推测,为什么你有备份,镜像,也可能是偶数复制。但它'不是一些软件,如数据库,可以节省你。 - eloff.

传统的(SCSI,ATA)磁盘协议规范穿上'吨保证任何/所有部门写在突然断电的情况下,原子(但请参阅下面的NVMe规范的讨论)。但是,似乎默许同意非古代"真实"磁盘悄悄地尝试最好地提供此行为(例如Linux内核开发商Christoph Hellwig在2017年演示文稿中提到这款脱机; Linux&#34的失败 - 原子文件更新;)。

Warning: Can only detect less than 5000 characters

2015年惠普研究人员恢复了我们的删除时间表,编写了申请数据的纸质失败 - 原子更新Linux文件系统(PDF)(媒体),关于在Advfs的Linux港口引入新功能(Advfs最初是Dec&#39的一部分; s tru64):

如果使用新的O_Atomic标志打开文件,则其应用程序数据的状态将始终反映最新成功的Msync,FSYNC或FDataSync。 Advfs此外,还包括一个新的Syncv操作,它将更新组合到多个文件中的失败原子束[...]

2017年,Christoph Hellwig将实验补丁写为XFS提供O_atomic。在" Linux&#34的失败原子文件更新;谈话(幻灯片)他解释了他如何从2015纸上画出灵感(但没有多文件支持),并且拼图扩展了已经存在的XFS Refthink工作。然而,尽管最初的邮件列表后,在写作(2020年年中)的这个时间补丁集是不是在主线内核。

在2019年Linux管道工会议的数据库轨道期间,MySQL Developer Dimitri Kravtchuk询问是否有计划支持O_Atomic(链接进入拍摄讨论)。那些组装了上面的XFS工作,那个英特尔声称他们可以在Optane上做一个原子性,但Linux也没有提供一个界面来公开它,即谷歌声称在GCE存储上提供16kib atomicity。另一个关键点是许多数据库开发人员需要大于4kib atomicity的东西,以避免必须进行双重写作 - PostgreSQL需要8kib,MySQL需要16kib,显然Oracle数据库需要64kib。此外,Richard Hipp博士(SQLite数据库的作者)询问是否有' SA标准接口索取atomicity,因为今天sqlite使用F2FS文件系统' s通过自定义Ioctl()s的能力进行原子型更新IOCTL与一个文件系统相关联。克里斯回答说,随着时间的时间'没有任何标准,没有任何东西提供O_Atomic接口。

TLDR;如果您在物理磁盘上从应用程序的整体堆栈控制整个堆栈(因此您可以控制并限定整个批次),您可以安排使用磁盘原子需要的内容。如果你'重新在那种情况下或你谈论一般情况,你不应该依赖于原子的扇区。

当OS发送命令将扇区写入磁盘时是它的原子?

内核发送的扇区可能是原子的(假设一个扇区没有大于4kib)。在受控案例中(电池支持控制器,声称支持原子写入的NVME盘,供应商给您保证等的SCSI磁盘等)用户空间程序可能能够使用O_Direct,只要o_direct wesn' t恢复为缓冲,I / O DOTN' T在块层/合并的分开/合并在块层/您正在发送设备特定命令并绕过块层。但是,在常规情况下,内核和用户空间程序都无法安全地假设扇区写入原子性。

你能止于磁盘上的数据是x的数据,部分y和部分垃圾吗?

从规范角度来看,如果您正在谈论执行常规SCSI的SCSI磁盘(16)和在该写入中间发生的电源故障,那么答案是肯定的:扇区可能包含第X部分x,部分y和垃圾。在机上写入期间发生崩溃意味着从被写入的区域读取的数据是不确定的,并且磁盘可以自由地选择它作为来自该区域的数据返回的内容。这意味着所有旧数据,所有新数据,一些新旧,新的,所有零,所有零,随机数据等都是"法律"返回所述扇区的值。来自SBC-3规范的旧草稿:

如果在任务集中执行写入操作的一个或多个命令,则在丢失电源时正在处理(例如,由应用程序客户端产生特定于供应商的命令超时)或发生介质错误或硬件错误(例如,因为a可移动介质被错误地卸载),那些命令写入的逻辑块中的数据是不确定的。当通过执行读取或验证操作的命令访问(例如,安装可移动介质后电源之后),设备服务器可以在这些逻辑块中返回旧数据,新数据或特定于供应商特定数据。

在读取遇到此类失败的逻辑块之前,应用程序客户端应重新发出执行未完成的编写操作的任何命令。

1在2018年谷歌宣布它已经调整了云SQL堆栈,这使得它们使用16k原子写入yinodb_doublewrite = 0通过o_direct ...谷歌执行的底层的自定义,被描述为在虚拟化存储中,内核,Virto和Ext4文件系统图层。此外,不再有可用的测试版标题为16 kB持久磁盘和MySQL(存档副本)的最佳实践描述了最终用户必须要安全地使用该功能。包括更改:使用适当的Google提供VM,使用专用存储,更改块设备参数并仔细创建具有特定布局的Ext4文件系统。但是,在2020年的某些时间点,本文档从GCE和#39中消失了,建议不支持这种最终用户调整。

4我认为大多数人在更高的抽象中工作,但如果您正在编写文件系统或数据库,那么您可能需要依赖于磁盘的原子操作 - 而不支持与第39岁的硬件提供保证。 - eloff.

@eloff按照您所说,原子扇区写入可以是优化,但您需要保证没有设置提供。单个扇区写入可能是原子的,但没有额外的工作,其中没有任何工作'没有什么可以阻止它相对于其他&#34重新排序;飞行和#34;如果有任何类型的挥发性缓冲,则写入 - 在那种情况下,当I / O已被下层接受时,您仍然可以作为屏障。 FWIW SQLite取决于扇区写入线性,而不是扇区默认情况下写下,但可以更改此功能。 - Anon.

我同意这一点,但基本上是如果你'重新编写文件系统或使用原始块设备的数据库,您需要像原子写作和障碍等原语。如果一个磁盘没有提供这两件事中的一个,或者以深奥的方式做到这两件事,你基本上可以' t支持那个硬件 - 它和#39;从根本上破碎。似乎原子行业写作是原子性几乎普遍的保证。对于障碍,有特殊的操作来订购您&#39的磁盘类型;重新使用(SCSI,SATA,NVM等)。 - eloff.

@eloff我几乎同意你的看法。我认为,我们'再既要说的是,你需要一种方法来知道什么时候写全做了它对非易失性介质。您可以控制哪些原始和保证您如何最佳。例如,如果我拥有的只是一种了解磁盘和#39; S缓存已经刷新的方法我可以模拟障碍(以价格)。我也可以采取日志方法来模拟原子。我' d争论没有破碎,但很可能会慢(呃)。奇怪的Linux用于暴露块层的障碍,但由于复杂性和错误,它摆脱了它们。 - Anon.

我认为撕裂的页面不是问题。据我所知,所有驱动器都有足够的功率,以在电源发生故障时完成写入当前扇区。

至少当到数据库时,知道事务已提交给磁盘时,每个人都在谎言。数据库发出一个fsync,并且操作系统只返回所有未完成的写入磁盘时,对右?也许不会。它'尤其是raid卡和/或sata驱动器,因为您的程序被告知一切都致力于(即fsync返回),但在驱动器上还没有数据。

您可以尝试使用BRAD' s diskchecker,了解您要用于数据库的平台是否可以在不丢失数据的情况下挽回插头。底线:如果DiskChecker失败,则该平台不安全运行数据库。具有酸的数据库依赖于知道事务何时致力于备份商店以及何时未知。这是真的数据库是否使用写入前瞻性的逻辑(如果数据库返回给用户而不完成FSYNC,则在发生故障时会丢失事务,因此不应声称它提供酸语义)。

在PostgreSQL邮件列表中讨论耐用性,在那里'它开始谈论SSD,但是它进入SATA驱动器,SCSI驱动器和文件系统。您可能会感到惊讶地学习您的数据可能是如何丢失的。它是一个具有需要耐用性的数据库的任何人的好主题,而不仅仅是那些正在运行PostgreSQL的那些。

2您是正确的,您必须使用在数据不现宜时正确报告回操作操作系统的存储设备部署数据库,否则无法使用酸中的D.当页面大小(写大小)是扇区大小的倍数时,有撕裂的页面,但只要驱动器完成写入当前扇区,并将fsync正确报告给操作系统,撕裂的页面可能是最糟糕的情况通常遇到。 - eloff.

我希望在未来的硬件设计中看到的一件事是CPU和磁盘的能力是在没有绝对围栏的情况下执行订购的能力。例如,有一台计算机能够讲述一个驱动器"有时写x,有时候y;然而,您可以相对于其他事项订购,但绝对不会在x&#34之前写y。同样,有一个CPU了解对象引用,以保证将无法更新对象引用,直到所有待处理到对象都已完成 - 没有强制订单相对于其他内容。如果有人追求此类概念,任何想法' - Supercat

没有人似乎同意这个问题。所以我花了很多时间尝试不同的谷歌查询,直到我终于找到了一个答案。

从Stephen Tweedie博士,Redhat员工和Linux内核文件系统和虚拟内存开发人员在ext3(他开发)成绩单的谈话中。如果有人知道,它' D成为他。

"它不仅仅是将这件事写入日记,因为那里的日志中的一些标记,所说:嗯,(实际上有这个日记记录)是这样的实际上代表磁盘的完整一致性?与您这样做的方式是拥有一些原子操作,它将该交易标记为在磁盘&#34上完成; [23m,14s]

"现在,这些天的磁盘实际上是制作这些保证。如果将写入操作启动到磁盘,即使电源在该扇区的中间故障,磁盘也有足够的功率,它实际上可以从主轴的旋转能量窃取电源;它有足够的力量来完成现在写作的扇区。在所有情况下,磁盘都可以保证。" [23m,41s]

5看起来很古老,因为它只提到了ext2。母牛文件系统仅是一个较低的有效方法来解决与日记文件系统相同的问题 - 所以即使呈现的想法也是旧的。我仍然会说stephen tweedie很可能是那个在这里纠正的那个。 - eloff.

我恭敬地不同意Tweedi博士。虽然驱动器制造商确实试图防止它们,但仍可以发生分裂部门并确实发生。分裂部门是半新的,半年。这导致扇区上的ECC错误,最终将主机报告为读取错误。从电动机(窃取旋转动力)使用后退EMF为电源驱动器是有问题的,因为当您为电子设备提供电时,速度慢速速度,并且由于在写入数据的频率时,旋转速度逐渐变慢,从开始完成后更改为完成读取电路难以锁定到信号上。 - 沸腾

制造商通常使用小帽和专用功率损耗检测电路来防止分裂扇区,但并非所有驱动器都是平等对待的。 但是,如果命令用FUA(强制单元访问)发送到驱动器(强制单元访问),则据说数据被保证到 ......