【问题标题】:How can databases guarantee persistency if it eventually depends to OS?如果最终依赖于操作系统,数据库如何保证持久性?
【发布时间】:2013-11-21 21:31:38
【问题描述】:

据我所知,当我们发出一条 SQL 语句时,数据库中的默认行为(肯定在 MySQL 中)是自动提交。
但结构通常如下:

String sqlInsertOrUpdateStatement = "....";  
sqlStatement.execute(sqlInsertOrUpdateStatement);  
//rest of code  

现在execute 是一个阻塞函数,当它返回时,我们知道数据是否已保存(根据执行结果)。
但我无法理解的是:
所有数据库实现都使用最低级别的文件。例如INSERT 基本上是对文件的深入写入操作。但是当我们写入文件时,我相信内容实际上并没有立即刷新。当操作系统决定时,它们会被刷新。即使应用程序代码(例如 C 库)发出刷新,操作系统也会很快刷新数据。
那么数据库如何保证持久性。我忽略/误解了文件 I/O 和操作系统中的一些基本内容吗?

【问题讨论】:

    标签: mysql database linux windows file


    【解决方案1】:

    嗯,在 Linux 数据库管理系统上使用 fsync 调用,它实际上是这样做的:保证数据被写入到磁盘。像 Oracle 这样的一些大型系统也会跳过文件系统(它执行您所说的由操作系统完成的事情)并自己写入驱动器上的扇区(当然会提高速度)。

    如果您想质疑耐用性...硬盘驱动器也可能出现故障,即使是大容量的 ;-)

    【讨论】:

    • 那么只有 Oracle 和 Linux 中的数据库保证持久性?
    • 你不能这么说。当然,其他操作系统也提供类似的功能,而其他数据库系统也使用类似的技术。这些只是我知道的例子,但我很确定 MySQL 也能保证持久性。
    • 你如何绕过文件系统?拥有特殊的写入权限和大量的程序集?
    • 不,更简单:通过管理访问 (root),您只需打开代表您的硬盘驱动器(或分区)的块设备并写入它。您不需要任何程序集...同样,不知道它是如何在 Windows 中完成的,但在 Linux 中很容易:只需 fopen("/dev/sda1/", "r") 就可以了。
    • 这意味着数据库以 root 访问权限运行。我的印象是出于安全原因这是不赞成的(不是说禁止的)。这是否意味着在 root 中安装数据库使其更可靠在写操作中?另外,如果安装在非 root 下,db 使用不同的层与 FS 交互?
    【解决方案2】:

    数据库不保证任何东西,它们不控制从数据库到存储中的位的整个堆栈,那么它们怎么能呢?

    他们可以做的是确保他们调用适当的函数,如果假设成立,将保持持久性。

    它的工作方式是程序写入数据库。数据库(通常)将该写入操作转换为日志事件,然后调用 fsync 将日志缓冲区刷新到磁盘。

    但是看,这里涉及到几个抽象。第一个是数据库级别的缓冲。 DB 使用适当的信息更新日志缓冲区,然后将这些缓冲区写入某种 I/O 流。

    如果它们是使用 stdio 编写的,它再次缓冲数据(不太可能,但谁知道),那么它们将不得不对该流调用 flush 以强制系统调用将缓冲区“写入磁盘”。

    但是,正如您所观察到的,写入“磁盘”意味着写入更多缓冲区。因此,fsync 调用相当于 stdio 的刷新调用。它告诉操作系统将进程数据写入磁盘。但这究竟意味着什么?这意味着操作系统调用适当的设备驱动程序将底层块写入物理设备。

    好吧,设备驱动程序可以说“Okey dokey”而不做任何事情。他们通常不会,但他们可以。司机可以为所欲为。我们假设发生的是驱动程序获取数据缓冲区,然后开始通过适当的接口(SATA、SCSI、iSCSI、NFS、USB 等)与硬件通信。

    这里的问题是,司机到底在和什么说话?好吧,今天,使用现代 SATA 驱动器,它正在与另一台计算机通信。这台计算机是磁盘驱动器的控制器。

    您知道磁盘驱动器上的控制器是做什么的吗?它们将数据缓冲到 RAM 中。所以,有可能你可以做“一切正确”(stdio flush、fsync、驱动程序写入块设备)并且仍然有数据,在 RAM 中,等待失败,坐在大约 50 美元的硬盘上,上面写着“Aok boss!” .

    有些驱动器默认说“okey dokey”,只是将数据存储在缓冲区中,需要另外配置。其他驱动器默认开箱即用。如果您将前一种驱动器配置不正确,用于数据库或 RAID 系统,那么,如果您断电,就会出现问题。

    否则设备将正确配置并愉快地将块写入坏扇区,而您从一开始就注定要失败。 C´est la vie。

    另外,请考虑您是否正在与驱动程序、网络、SAN 控制器通信,以及在写入阵列之前使用电池备份 RAM 缓存...希望如此。

    因此,数据库不保证任何事情。相反,他们会进行尽职调查,以确保将数据安全地传送到实际的物理设备,以及该数据最终将实际保存到的位置。

    任何称其使用 ACID 的数据库都可以做到这一点,并且所有操作系统都支持这一点——当然,任何人都会实际使用的所有操作系统。

    底线,如果你想确保你的数据在磁盘上,在 Unix 中,你调用 fsync。在 Windows 中,你称之为“无论谷歌说你在 Windows 上调用 fsync 的东西”。那时实际发生的事情不在你的掌控之中,所以最好向那些了解你的硬件和接口的人提问。然而,程序已经完成。

    附录:

    现代数据库通常的工作方式是将数据组织在磁盘上的“表”中,并且通常单独作为“索引”进行组织。因此,您可以想象,如果您有一个包含 1000 行的表,它以 100 个“页”存储在磁盘上,您可以看到如果更新了第 500 行,您将需要更新第 50 页。您还可以看到,如果更新第 700、500、600 行,则需要更新第 70、50 和 60 页。

    好吧,事实证明,磁盘驱动器作为流媒体设备工作得非常快。当您必须移动磁盘磁头(在驱动器上来回移动的手臂)时,它会显着减慢速度。因此,您可以在上面的示例中看到,磁盘磁头在写入操作期间来回弹跳。

    现在,带有事务的数据库也需要某种日志。日志是记录所有操作的地方。日志通常也只附加到,因此如果您要更新上面的那些行,它们将在日志中被捕获为 3 个连续事件。

    所以 DB 所做的是,当您更改一行时,它会更新内部缓冲区,即第 50 页的内部副本。当数据库想要去获取第 500 行的另一个副本时,它会看到它已经在 RAM 中有一个副本,并且不需要去磁盘。一旦它更新了内部缓冲区,它就会将操作正确地写入日志。由于这些是顺序的,因此它们要快得多。最后,它将使用 fsync 等提交写入。每次提交事务时,它都会立即执行此操作。在您“确定”数据记录在某处之前,您不能提交事务。

    此时,内存中有行,日志中捕获的行(持久),但磁盘上的实际页面已过期。对于正在运行的数据库,这不是问题。最终,系统将“检查点”。这会获取所有过期的日志条目,并将它们复制到磁盘上的最终目的地,同步日志、缓冲区和磁盘。当它这样做时,它将对磁盘的写入进行排序。所以上面不是写第 60 页,然后是第 50 页,然后是第 70 页,而是按顺序写它们:50、60、70。更少的寻头,更好的性能。

    现在,如果系统在此之前崩溃,那没问题。我们已经将数据安全地保存在日志中。因此,当系统恢复正常时,它会进入“恢复”状态。恢复基本上是对日志中已提交的所有数据(即它们的事务已完成)运行检查点过程,并像以前一样将它们刷新到磁盘页面。它会在让数据库启动并可以访问之前执行此操作。

    至于配置驱动器,据我了解,有一些实用程序可以将参数配置写入驱动器。取决于操作系统,我真的不知道细节。你必须用谷歌搜索它。

    【讨论】:

    • +1。谢谢你的详细描述!我有几个问题 1)database (typically) convert that write operation in to a log event, and then calls fsync to flush the log buffers to disk 日志事件是什么意思? 2)这个日志事件被缓冲,线程返回给调用者,日志事件是fsynced最终?我不确定我是否关注你。 3)If you use the former kind of drives, improperly configured, for a database第一次听说这个配置怎么设置?喜欢操作系统的设置? (例如右键单击磁盘?)
    • 非常有趣的更新!有两部分我不明白。1)你提到了一个单独的日志文件和“实现”表的实际文件。然后你提到当数据是最终被写入后一个位置(实际位置),我们有优势对磁盘的写入进行排序,从而获得更好的性能。但是写入的排序不是仅由设备控制器完成吗?我们可以在您描述的应用程序级别对写入进行排序吗? 2)这些日志文件是额外的存储空间。它们是否曾经被删除以释放空间?
    猜你喜欢
    • 2011-10-15
    • 1970-01-01
    • 2020-06-12
    • 2018-02-13
    • 1970-01-01
    • 1970-01-01
    • 2013-10-21
    • 2015-07-03
    • 1970-01-01
    相关资源
    最近更新 更多