0
点赞
收藏
分享

微信扫一扫

数据库中事务的ACID四大特性详解

代码小姐 2022-01-05 阅读 76

这里写目录标题


事务:一个最小的不可再分的工作单元;通常一个事务对应一个完整的业务,一个完整的业务需要批量的DML(insert、update、delete)语句共同联合完成。

ACID四大特性之中,C(一致性)是目的,A(原子性)、I(隔离性)、D(持久性)是为了保证一致性,数据库提供的手段。数据库必须要实现AID三大特性,才有可能实现一致性。

一致性

一致性:执行事务前后,数据保持一致,多个事务对同一个数据读取的结果是相同的。

Mysql怎么保证一致性的?

这个问题分为两个层面来说:

  1. 从数据库层面,数据库通过原子性、隔离性、持久性来保证一致性。也就是说ACID四大特性之中,C(一致性)是目的,A(原子性)、I(隔离性)、D(持久性)是手段,是为了保证一致性,数据库提供的手段。数据库必须要实现AID三大特性,才有可能实现一致性。
  2. 从应用层面,通过代码判断数据库数据是否有效,然后决定回滚还是提交数据。

原子性

原子性:事务是最小的执行单位,不允许分割。事务的原子性确保动作要么全部完成,要么完全不起作用。

Mysql怎么保证原子性的?

利用Innodb的undo log,undo log名为回滚日志,是实现原子性的关键。

undo log记录了这些回滚需要的信息,当事务执行失败或调用了rollback,导致事务需要回滚,便可以利用undo log中的信息将数据回滚到修改之前的样子。

隔离性

隔离性:并发访问数据库时,一个用户的事务不被其他事务所干扰,各并发事务之间数据库是独立的。

Mysql怎么保证隔离性的?

Mysql保证隔离性利用的是锁和MVCC机制。

MVCC,即多版本并发控制(Multi Version Concurrency Control),一个行记录的数据有多个版本的快照数据,这些快照数据在undo log中。如果一个事务读取的行正在做DELELE或者UPDATE操作,读取操作不会等行上的锁释放,而是读取该行的快照版本。

快照读和当前读

快照读:读取的是快照版本,也就是历史版本。
当前读:读取的是最新版本。

普通的SELECT就是快照读,而UPDATE、DELETE、INSERT、SELECT … LOCK IN SHARE MODE、SELECT … FOR UPDATE是当前读。

MVCC如何实现

在InnoDB中,给每行增加两个隐藏字段来实现MVCC,一个用来记录数据行的创建时间,另一个用来记录行的过期时间(删除时间)。在实际操作中,存储的并不是时间,而是事务的版本号,每开启一个新事务,事务的版本号就会递增。

于是乎,默认的隔离级别(REPEATABLE READ)下,增删查改变成了这样:

  1. SELECT:读取创建版本小于或等于当前事务版本号,并且删除版本为空或大于当前事务版本号的记录。这样可以保证在读取之前记录是存在的。
  2. INSERT:将当前事务的版本号保存至行的创建版本号。
  3. UPDATE:新插入一行,并以当前事务的版本号作为新行的创建版本号,同时将原记录行的删除版本号设置为当前事务版本号。
  4. DELETE:将当前事务的版本号保存至行的删除版本号。

持久性

持久性:一个事务被提交之后。它对数据库中数据的改变是持久的,即使数据库发生故障也不应该对其有任何影响。

Mysql怎么保证持久性的?

利用Innodb的redo log。Mysql是先把磁盘上的数据加载到内存中,在内存中对数据进行修改,再刷回磁盘上。当做数据修改的时候,不仅在内存中操作,还会在redo log中记录这次操作。当事务提交的时候,会将redo log日志进行刷盘(redo log一部分在内存中,一部分在磁盘上)。当数据库宕机重启的时候,会将redo log中的内容恢复到数据库中,再根据undo log和binlog内容决定回滚数据还是提交数据。

采用redo log的好处? 其实好处就是将redo log进行刷盘比对数据页刷盘效率高,具体表现如下:

  1. redo log体积小,毕竟只记录了哪一页修改了啥,因此体积小,刷盘快。
  2. redo log是一直往末尾进行追加,属于顺序IO。效率显然比随机IO来的快。
举报

相关推荐

0 条评论