sqlite 表与表之间的关系_关系型数据库进阶之Log Manager

点上面“东哥IT笔记”,关注并星标

每天一篇业界最新技术分享


我们在之前的文章中聊到,数据库为了提高它的性能,会把数据存在memory buffer中。但是这里有一个问题,就是假如一个已经committedtransaction crash掉了,你因为这个crash丢掉了memory中的数据,那就会出现了Durability的问题。当然你也可以把所有的数据都写到磁盘中,但是同样的问题,假如写到一半就crash了,这里就会发生原子性的问题。

所以这里我们的原则是任何通过transaction进行写的修改都要么是全部完成要么就是什么都不做。

为了解决这个问题,有两个方法:

  • Shadow copies/pages: 每一个transaction都创建它自己的数据库(或者部分数据库)备份,然后在这个备份上进行操作。假如有错误,这个备份就移除掉。假如成功了,就切换到这个备份上,而把旧的备份删除掉。

  • Transaction logtransaction log是一个存储空间。在把数据写到磁盘之前,数据库把相关的信息写到transaction     info中,因此即使有crash或者cancel的时候,数据库也知道怎么来完成或者移除响应的没有完成的transaction

WAL

Shadow copies/pages的思想其实很好,唯一的问题就是在大的数据库中,会额外浪费很多磁盘的空间。这也是为什么现在主流的数据库都是用transaction log来解决这个问题。Transaction log必须存储在一个稳定的存储空间中。

大多数数据库(至少Oracle SQL ServerDB2 PostgreSQL MySQL以及SQLite)都使用Write-Ahead Logging protocol (WAL)来处理transaction log。这个protocol主要有三个规则:

  • 每一个对数据库的修改都产生一个log记录,并且log记录必须在数据写到磁盘前写到transaction     log中。

  • log记录必须按照顺序写,也就是说发生在记录A先发生,那么记录A就必须先写。

  • 当一个transaction     committed了,这个commit的顺序必须在transaction介绍前写到transaction     log

2dff6fe23b9dc7de646b1c7ef7bcb0eb.png

这些工作都是在log manager中处理的,他位于cache managerdata access manager之间,比如每一个更新,删除,创建,commitrollback都需要写到transaction log中。听起来很简单,对吧?这里最大的问题就是性能问题,总的说就是假如transaction log很慢,那么它就会让所有的东西都慢起来。

ARIES

1992年,IBM开发了一个加强版本的WAL,我们称之为ARIES。现在ARIES总归多多少少在现代数据库中被使用。关于ARIES,推荐大家去读读这个论文。这里就是简单概括一下:

ARIES就是Algorithms for Recovery and Isolation Exploiting Semantics。这个技术就两个目的:

  • 当写log的时候有很好的性能。

  • 有一个快的和可靠的恢复。

有很多原因数据库都会rollback一个transaction

  • 用户取消了它

  • server或者网络错误

  • 因为transaction破坏了数据库的完整性(比如数据中有一个UNIQUE的列,然后这个transaction加入了一个重复的列)

  • 因为死锁

有时候,数据库需要能恢复transaction(比如有网络的错误等),那怎样实现这个恢复呢?在回答这个问题之前,我们先来看看有哪些信息被存储在log记录中。

Logs

每一个transaction过程中的操作(add/remove/modify)都会产生一个log,这个log的记录由下面这些部分组成:

  • LSN: 这是一个唯一的Log Sequence NumberLSN是按照时间顺序来记录的*,这也就意味着假如操作A在操作B前面发生,那么log ALSNlog BLSN要小。

  • TransID:产生这个操作的transactionid

  • PageID: 修改数据所在的磁盘的位置。

  • PrevLSN:指向同一个transaction中的上一个log记录。

  • UNDO:去除这个操作影响的方式。比如假如一个操作是更新,那UNDO就会保存更新值之前的value/state,这样就可以很方便地做UNDO的操作。

  • REDO:重放这个操作的方式。这里有两个方式来做这件事。要不你保存操作之后的value/state,要不你保存这个操作本身,这样就可以重放。

  • 。。

为了给你一个更好的理解,我们来看一个简单的例子:UPDATE FROM PERSON SET AGE = 18;我们假设这个查询是在transaction 18中执行的。

0d1fe827467dd911232cea3c96b25178.png

每一个log都有一个独立的LSN。这些log在同一个transaction是连接在一起的。这个log是更加时间顺序来进行连接的。

Log Buffer

为了防止log的写入成为瓶颈,这里会使用log buffer

4c34f2c3e7047fa660a3557b63c0979b.png

query执行器请求一个修改的时候:

1)这个cache manager保存相应的修改到一个buffer

2)log manager保存相应的log到它的buffer

3)这一步,query执行器会认为这个操作完成了(也意味会有别的修改)

4)log manager会把相关的log写到transaction log中。什么时候写是由算法决定的。

5)cache manager把相关的修改写到磁盘中。什么时候把数据写到磁盘中也是由算fan决定的。

transaction commit的时候,也就意味着步骤1,2,3,4,5都已经完成了。写数据到transaction log是非常快的,因为它只是“加一个logtransaction log中某偶一个地方”,而把数据写到磁盘则是更加复杂的一件事。

STEALFORCE策略

为了性能,有时候上面的步骤5会在commit之后才完成。因为即使这时候发生crash,也能够通过REDO logs来回复。我称之为NO-FORCE策略。

当然数据库也可以选择FORCE策略(步骤5必须在commit之前完成)来降低恢复的负载。

另外一个问题是数据是否一步一步写到磁盘中(STEAL策略)或者buffer manager是否需要等待commit顺序来把所有的数据一次性写到如(NO-STEAL)。究竟是选择STEAL还是NO-STEAL取决于你想要什么:更快的写入,但是恢复很慢还是更快的恢复?

下面是这些选择的影响:

  • STEAL/NO-FORCE需要UNDOREDO:性能最好,但是提高了log的复杂度以及恢复的流程。如何选择取决于具体的数据库。

  • STEAL/FORCE只需要UNDO

  • NO-STEAL/NO-FORCE仅仅需要REDO

  • NO-STEAL/FORCE什么都不需要:但是性能也是最差的,而且需要最大的ram

恢复的部分

现在我们有了log,让我们来看看如何来使用它。

假设现在数据库crash了,我们重启了数据库,并且开始进行恢复的流程:

ARIES根据三个pass中从crash中恢复:

  1. 分析pass:恢复的流程从所有的transaction log中读取整个时间性,并且看看在crash发生的时候究竟发生了什么。这也决定了哪一个transaction来进行rollback,并且哪些数据需要在crash的时候写到磁盘中。

  2. Redo pass:这个pass就是根据上面分析pass中得到的log记录来使用REDO更新数据库的状态。在REDO的过程,REDOlog是根据时间顺序来执行的。

对每一个log,恢复的过程先读取page中的LSN:假如LSN(page_on_disk)>=LSN(log_record),这就意味着数据已经在crash之前写入到了磁盘中。所以不需要做什么。假如LSN(page_on_disk) < LSN(log_record),则需要更新磁盘中的相应page

  1. Undo pass:这个passroll back所有在crash之前没有完成的transactionrollback从每一个transaction的最后的log开始,按照逆时间的顺序执行UNDO log

这里分析phase的目的就是使用transaction log来发现crash发生之前发生了什么。为了加速这个过程,ARIES提供了一种称之为checkpoint的概念。总的思想就是把transaction表和dirty page表以及最新的LSN不时写入磁盘中,所以在分析pass过程中,只要分析LSN后面的log就可以了。

至此,我们就完成所有关系型数据库进阶分析,这些内容真的很多,但很开心我们终于写完了,希望大家能够喜欢。

相关文章:

关系型数据库进阶之总体架构

关系型数据库进阶之客户端管理

关系型数据库进阶之查询管理

关系型数据库进阶之查询优化

关系型数据库进阶之查询优化二

关系型数据库进阶之数据管理

关系型数据库进阶之Transaction manager

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值