【数据库】数据库如何保证原子性

写在最前,本人也只是个大三的学生,如果你发现任何我写的不对的,请在评论中指出。

今天网上冲浪的时候,看到有人发了面试题,问的是数据库如何保证原子性的,都知道事务里原子性的意思:一个事务包含多个操作,这些操作要么全部执行,要么全部不执行。但现在问是如何保证的,那就是我的知识盲区了,看到群里大佬们争先恐后的漂亮回答,原来只有我一个人菜得真实嘛?
【数据库】数据库如何保证原子性_第1张图片

后面我又去百度搜搜抄抄,总结了下面的知识点:

binlong

什么是binlog

先说说这家伙,binlong就是记录了数据库结构和表数据变更, 就是对进行了update/delete/insert/truncate/create进行记录(简单理解就是存储着每条变更的SQL语句)

binlong用来做什么

主要用于:复制和恢复数据

一般公司会采用一主多从的结构,从服务器需要和主服务器的数据保持一致,这就需要通过binlong来实现。因为binlong记录了数据库表的变更,所以我么可以用binlong进行数据恢复

redolog

redolong又是干嘛的?

假设你有位同事要辞职,上层需要你去执行一条sql语句删除这位同志的信息:

delete from sys_user where name='XX'

但你鬼迷心窍突然修改name="bossName"并按下了执行,然后你突然醒悟,手疾眼快在0.01s的时候按下了电源键。好,问题就出现了:我们都知道mysql的基本存储结构都是,所以MYSQL是先把这条记录在页里找到,然后加载到内存对对应数据进行修改, 现在就存在一个问题,如果内存中数据改了, 还没来及落磁盘, 而此时数据库挂了, 还能不能找回这次操作(指丢失饭碗)
【数据库】数据库如何保证原子性_第2张图片
MYSQL引入了redolog, 内存写完了,会再写一份redolog, 这份redolog会记载这次在某个页上做了什么修改,然后将数据异步刷新到磁盘中,毕竟如果每个请求都将数据马上落到磁盘后,不说速度慢,MYSQL可能都遭不住。

所以,redolog的存在就是为了当我们修改的时候,写完内存了,但数据没来及写到磁盘。此时我们的数据库挂了,我们就可以根据redolog来对数据进行恢复。

binlog和redolog

看到这里你可能疑惑两者都是数据进行恢复的,那区别呢?

存储的内容

binlog记录的都是一些SQL语句,而redolog记录的都是物理修改的内容,所以说前者记录的是数据的逻辑变化,后者记录的是物理变化

写入细节

redolog 是MYSQL的InnoDB引擎所产生的。
binlog无论啥MYSQL用什么引擎,都会有的。

InnoDB的事务的持久性就是靠redolog来实现的, 上面也提到了binlog记录变更的内容(逻辑),redolog也会记录变更的内容(物理),那么他们的写入顺序是什么样的呢?

redolog 是事务开始的时候,就开始记录每次的变更信息,而binlog是在事务提交的时候才记录

于是新有的问题又出现了:我写其中的某一个log,失败了,那会怎么办?现在我们的前提是先写redo log,再写binlog,我们来看看:

  • 如果写redo log失败了,那我们就认为这次事务有问题,回滚,不再写binlog
  • 如果写redo log成功了,写binlog,写binlog写一半了,但失败了怎么办?我们还是会对这次的事务回滚,将无效的binlog给删除(因为binlog会影响从库的数据,所以需要做删除操作)
  • 如果写redo log和binlog都成功了,那这次算是事务才会真正成功。

简单来说,是需要两者配合才能达到数据的一致性

过程:

  • 阶段1:InnoDBredo log 写盘,InnoDB 事务进入 prepare 状态
  • 阶段2:binlog 写盘,InooDB 事务进入 commit 状态
  • 每个事务binlog的末尾,会记录一个 XID event,标志着事务是否提交成功,也就是说,恢复过程中,binlog 最后一个 XID event 之后的内容都应该被 purge。

undolog

回归主题, 数据库如何保证原子性的

undolog存储的也是逻辑日志,比如我们要insert一条数据了,那undo log会记录的一条对应的delete日志。我们要update一条记录时,它会记录一条对应相反的update记录。

这也应该容易理解,毕竟回滚嘛,跟需要修改的操作相反就好,这样就能达到回滚的目的。因为支持回滚操作,所以我们就能保证:“一个事务包含多个操作,这些操作要么全部执行,要么全都不执行”——原子性。

因为undo log存储着修改之前的数据,相当于一个前版本,MVCC实现的是读写不阻塞,读的时候只要返回前一个版本的数据就行了。

你可能感兴趣的:(数据库,数据库)