原子性

实现原理:利用 undo log。

undo log 名为回滚日志,是实现原子性的关键,当事务回滚时能够撤销所有已经成功执行的 sql 语句,他需要记录你要回滚的相应日志信息:

  • 当你 delete 一条数据的时候,就需要记录这条数据的信息,回滚的时候,insert 这条旧数据
  • 当你 update 一条数据的时候,就需要记录之前的旧值,回滚的时候,根据旧值执行 update 操作
  • 当年insert一条数据的时候,就需要这条记录的主键,回滚的时候,根据主键执行 delete 操作

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

持久性

实现原理:利用 redo log。

MySQL 先把磁盘上的数据加载到内存,在内存中进行修改,再刷回磁盘。如果此时突然宕机,内存中的数据将会丢失。

如何解决这个问题?

事务提交前直接把数据写入磁盘?这样做存在以下的问题:

  • 只修改一个页面里的一个字节,就要将整个页面刷入磁盘,太浪费资源了。毕竟一个页面 16kb 大小,你只改其中一点点东西,就要将 16kb 的内容刷入磁盘,听着也不合理。
  • 毕竟一个事务里的 SQL 可能牵涉到多个数据页的修改,而这些数据页可能不是相邻的,也就是属于随机 IO。显然操作随机 IO,速度会比较慢。

于是,采用 redo log 解决上面的问题。当修改数据时,不仅在内存中修改,还会在 redo log 中记录这次操作。当事务提交的时候,会将 redo log 日志进行刷盘(redo log 一部分在内存中,一部分在磁盘上)。当数据库宕机重启的时候,会将 redo log 的内容恢复到数据库中,再根据 undo log 和 bin log 来决定回滚还是提交数据。

采用 redo log 的好处(相对直接将数据写入磁盘):

  • redo log 体积小,只记录了哪一页修改了什么,刷盘快。
  • redo log 是一直往末尾追加,属于顺序 IO。效率更高。

隔离性

实现原理:锁 + MVCC。

锁很简单,就是事务在修改数据的时候需要获取锁、上锁之类的操作。

MVCC:多版本并发控制(Multi Version Concurrency Control),一个行记录数据有多个版本对快照数据,这些快照数据在 undo log 中。

如果一个事务读取的行正在做 DELELE 或者 UPDATE 操作,读取操作不会等行上的锁释放,而是读取该行的快照版本。

一致性

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

数据库本身提供保障,例如不允许向整形列插入字符串值、字符串长度不能超过列的限制等。

应用层面进行保障,例如如果转账操作只扣除转账者的余额,而没有增加接收者的余额,无论数据库实现的多么完美,也无法保证状态的一致。

评论




博客内容遵循 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 协议

载入天数...载入时分秒... 本站使用 Volantis 作为主题 鲁ICP备-20012065号