为什么SQL数据库在命令日志中使用预写日志?

时间:2013-01-06 10:19:19

标签: sql database logging transactions voltdb

我读到了关于Voltdb的command log。命令日志记录事务调用,而不是像在预写日志中那样更改每一行。通过仅记录调用,命令日志保持最低限度,从而限制磁盘I / O对性能的影响。

任何人都可以解释为什么Voltdb使用命令日志背后的数据库理论以及为什么标准SQL数据库(如Postgres,MySQL,SQLServer,Oracle)使用预写日志?

6 个答案:

答案 0 :(得分:75)

我认为最好改写一下:

  

为什么新的分布式VoltDB使用命令日志而不是预写日志?

让我们做一个实验,并想象您将编写自己的存储/数据库实现。毫无疑问,您已经足够先进,可以抽象文件系统并使用块存储以及一些额外的优化。

一些基本术语:

  • 状态:在给定时间点存储的信息
  • 命令:指令存储更改其状态

所以你的数据库可能如下所示:

enter image description here

下一步是执行一些命令:

enter image description here

请注意几个重要方面:

  1. 命令可能会影响许多存储的实体,因此很多块会变脏
  2. 下一个状态是当前状态和命令
  3. 的函数

    可以跳过某些中间状态,因为它足以代替一串命令。

    enter image description here

    最后,您需要保证数据的完整性。

    • 预先记录 - 核心概念是,在对永久存储进行大量更新之前,应记录状态更改。根据我们的想法,我们可以记录每个块的增量更改。
    • 命令记录 - 中心概念是仅记录命令,用于生成状态。

    enter image description here

    两种方法都有利弊。预写日志包含所有已更改的数据,命令日志将需要添加处理,但快速轻量级。

    VoltDB: Command Logging and Recovery

      

    命令日志记录的关键是它记录调用,而不是日志   交易的后果。通过仅记录调用,   命令日志保持最低限度,限制磁盘I / O的影响   有表现。

    附加说明

    SQLite: Write-Ahead Logging

      

    传统的回滚期刊的工作原理是写一份   原始未更改的数据库内容到单独的回滚日志中   文件,然后将更改直接写入数据库文件。

         

    当附加指示提交的特殊记录时发生COMMIT   到了WAL。因此,COMMIT可以在没有写入的情况下发生   原始数据库,它允许读者继续操作   原始未更改的数据库,同时进行更改   致力于WAL。

    PostgreSQL: Write-Ahead Logging (WAL)

      

    使用WAL可显着减少磁盘写入次数,   因为只需要将日志文件刷新到磁盘以保证   提交事务,而不是每个数据文件都已更改   通过交易。

         

    日志文件按顺序写入,所以   同步日志的成本远远低于冲洗日志的成本   数据页面。对于处理许多小型服务器的服务器尤其如此   交易涉及数据存储的不同部分。此外,   当服务器处理许多小并发事务时,一个   日志文件的fsync可能足以提交许多事务。

    <强>结论

    命令记录:

    1. 更快
    2. 占地面积较小
    3. 更重&#34;重播&#34;过程
    4. 需要经常拍摄快照
    5. 预先记录记录是一种提供原子性的技术。更好的命令日志记录性能还应该改善事务处理。 Databases on 1 Foot

      enter image description here

      <强>确认

      VoltDB Blog: Intro to VoltDB Command Logging

        

      通过ARIES样式记录进行命令记录的一个优点是a   可以在执行开始而不是执行之前记录事务   事务并等待日志数据刷新到磁盘。另一个   优点是命令日志所需的IO吞吐量是   由用于中继命令的网络限制,在这种情况下   Gig-E,这种吞吐量可以通过便宜的商品磁盘来满足。

      重要的是要记住VoltDB本质上是分布式的。因此处理事务有点棘手,性能影响显而易见。

      VoltDB Blog: VoltDB’s New Command Logging Feature

        

      VoltDB中的命令日志由存储过程调用和   他们的参数。在每个节点上创建一个日志,每个日志都是   复制,因为所有工作都复制到多个节点。这个   导致重复的命令日志,可以在重放时删除   时间。因为VoltDB事务是强有序的,所以命令   日志还包含订购信息。因此可以进行重放   按照原始交易的确切顺序,完整   事务隔离VoltDB提供。自从调用自己   通常比修改后的数据小,并且可以在之前记录   他们承诺,这种方法有一个非常适度的影响   性能。这意味着VoltDB用户可以实现同样的目标   平流层性能数字,具有额外的耐久性   保证。

答案 1 :(得分:1)

从Postgres'提前写http://www.postgresql.org/docs/9.1/static/wal-intro.html和VoltDB命令日志(你引用的)的描述中,我看不出太多差别。它似乎是具有不同名称的相同概念。

两者都只将日志文件同步到磁盘而不是数据,以便通过重播日志文件来恢复数据。

VoltDB的第10.4节解释说他们的社区版本没有命令日志,所以它不会通过ACID测试。即使在企业版中,我也没有看到他们的事务隔离细节(例如http://www.postgresql.org/docs/9.1/static/transaction-iso.html)让我觉得VoltDB和Postges一样严重。

答案 2 :(得分:0)

我读它的方式如下:(我自己的意见)

此处所述的命令记录仅记录发生的事务,而不记录事件中发生的事件。好的,所以这是一个神奇的部分...如果你想要回滚,你需要恢复最后一个快照,然后你可以重播之后应用的所有交易(在上面的链接中描述)。如此有效地恢复备份并重新应用所有脚本,只有VoltDB现在已经为您自动化了。

我看到的真正区别在于,您无法像正常的事务日志那样逻辑地回滚到某个时间点。正常的事务日志(MSSQL,MySQL等)可以轻松回滚到某个时间点(在正确的设置中),因为事务可以“反转”。

有趣的问题出现了 - 参考pedz的pos,即使使用命令日志,它是否也会通过ACID测试?会做更多的阅读......

添加:阅读更多,我不认为这对于非常繁忙的交易数据库来说是个好主意。在命令日志填满时会自动创建数据库快照,以便从大事务日志和用于此的IO中保存?如果您的快照定期完成,您将会产生大量IO,并且您还将内存用于边缘。 Alos,在我看来,你失去了在最后一次自动快照之前轻松回滚到某个时间点的能力 - 想想管理起来会非常棘手。

我宁愿坚持交易系统的交易日志。它已被证明并且有效。

答案 3 :(得分:0)

它只是一个粒度问题。它们在存储过程级别记录操作,大多数RDBMS记录在单个语句的级别(和“较低”)。他们对优势的模糊也是一点红鲱鱼:

  

通过ARIES样式记录进行命令记录的一个优点是a   可以在执行开始而不是执行之前记录事务   事务并等待日志数据刷新到磁盘。

他们必须等待记录命令,它只是一个小得多的记录。

如果我没弄错,VoltDB的交易单位是存储过程。传统的RDBMS通常需要支持包含任意数量语句的临时事务,因此程序级日志记录是不可能的。此外,传统的RDBMS中存储过程通常不是真正的确定性(即给定的参数+日志+数据总是产生相同的输出),为此它们必须使用它。

然而,对于这种受约束的RDBMS模型,性能改进将是巨大的。

答案 4 :(得分:0)

使用WAL,读者可以从未刷新的日志中读取页面。不对主DB进行修改。使用命令日志记录,您无法从命令日志中读取。

因此命令记录非常不同。 VoltDB使用命令日志记录来创建恢复点并确保持久性,当然 - 它实时写入主数据库存储(RAM) - 包括所有附带的锁定问题等。

答案 5 :(得分:0)

在我开始解释之前,很少有术语:

日志记录方案:数据库使用诸如Shadow paging,预写日志(WAL)等日志记录方案来实现并发性,隔离性和持久性(这是一个不同的主题)。

为了理解为什么WAL更好,让我们看看影子分页的问题。在影子分页中,数据库使用数据库的主版本和影子版本,因此,如果表大小为10亿,并且缓冲池管理器没有足够的内存来容纳脏页中的所有元组(记录),在未提交事务之前,不会将其写入主版本。

enter image description here

一旦提交所有事务,就切换标志,并且影子版本成为主版本。在上图中,Page 3 and Page 5较旧并且可以被垃圾回收。

  1. 此方法的问题在于,遗留了许多零散的元组,这些元组是随机放置的,与顺序访问脏页相比,这要慢一些,这就是“预写日志”的作用。 >

  2. 使用WAL的另一个优点是运行时性能(因为您没有执行随机IO刷新页面),但是恢复时间较慢。而使用影子分页,恢复性能更快(偶尔需要)。