关于java:彻底搞懂MySQL事务

40次阅读

共计 2062 个字符,预计需要花费 6 分钟才能阅读完成。

迎面走来了你的面试官,身穿格子衫,挺着啤酒肚,发际线重大后移的中年男子。
手拿泡着枸杞的保温杯,胳膊夹着 MacBook,MacBook 上还贴着公司标语:“我爱加班”。

面试开始,直入正题。

面试官: 看你简历下面写着精通 MySQL,我先问你事务的个性是什么?

陈词滥调,这个还有谁不会背的吗?

我: 这个我晓得,事务有四大个性,别离是原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability),简称 ACID。

原子性是指事务中所有操作要么全副胜利,要么全副失败。

一致性是指事务执行前后,数据始终处于一致性状态,不会呈现数据失落。

隔离性是指事务提交前的中间状态对其余事务不可见,即互相隔离。

持久性是指事务提交后,数据的批改永恒保留在数据库中。

面试官: 嗯,答复得不错。那你晓得 MySQL 底层是怎么实现事务的四大个性?

这道题有点深了,须要背会 redo log、undo log、mvcc。

千万别说不晓得这几个货色是干嘛用的。

岂但要晓得,还要跟事务扯上关系。

我: 原子性是 undo log 实现的,一致性是由代码逻辑层面保障的,隔离性是由 mvcc 实现的,持久性是基于 redo log 实现的。

Redo Log(重做日志):

Redo Log 记录的是物理日志,也就是磁盘数据的批改。
用来保障服务解体后,仍能把事务中变更的数据长久化到磁盘上。

如果没有 Redo Log 的话,会产生什么?

批改数据的过程就变成这样了:

  1. 从磁盘加载数据到内存
  2. 在内存中批改数据
  3. 把新数据长久化到磁盘

这样做,会有重大的性能问题。

  1. InnoDB 在磁盘中存储的根本单元是页,可能本次批改只变更一页中几个字节,然而须要刷新整页的数据,就很浪费资源。
  2. 一个事务可能批改了多页中的数据,页之间又是不间断的,就会产生随机 IO,性能更差。

所以为了进步写入性能,于是就引入了 Redo Log。

看一下引入 Redo Log 后批改流程:

  1. 从磁盘加载数据到内存
  2. 在内存中批改数据
  3. 把新数据写到 Redo Log Buffer
  4. Redo Log Buffer 中数据长久化到 Redo Log 文件中
  5. Redo Log 文件中数据长久化到数据库磁盘中

Undo Log(回滚日志):

Undo Log 记录的是逻辑日志,用来回滚事务时,复原到批改前的数据。

比方:当咱们执行一条 insert 语句时,Undo Log 就记录一条相同的 delete 语句。

退出 Undo Log 之后的批改流程就是这样的:

MVCC(多版本并发管制,Multi-Version Concurrency Control):

记录的是某个工夫点上的数据快照,用来实现不同事务之间数据的隔离性。

提到隔离性,肯定要说一下事务的隔离级别。

说事务隔离级别之前,必须要先说一下并发事务产生的问题:

脏读: 一个事务读到其余事务未提交的数据。

不可反复读: 屡次读取雷同的数据,失去的后果集不统一,即读到其余事务提交后的数据。

幻读: 雷同的查问条件,屡次读取的后果不统一,即读到其余事务提交后的数据。

不可反复读与幻读的区别是: 不可反复读是读到了其余事务执行 update、delete 后的数据,而幻读是读到其余事务执行 insert 后的数据。

隔离级别

Read UnCommitted(读未提交): 读到其余事务未提交的数据,会呈现脏读、不可反复读、幻读。

Read Committed(读已提交): 读到其余事务已提交的数据,解决了脏读,会呈现不可反复读、幻读。

Repeatable Read(可反复读): 雷同的数据,屡次读取到的后果集统一。解决了不可反复读,还是会呈现幻读。

Serializable(串行化): 所有事务串行执行,解决了幻读。

再谈 MVCC:

MVCC 解决了读写抵触,实现了读写并行,晋升了事务的性能。

因为 Read UnCommitted 隔离级别下,每次都读取最新的数据。而 Serializable 隔离级别下,对所有读取数据都加锁。这两种隔离级不须要 MVCC,所以 MVCC 只在 Read Committed 和 Repeatable Read 两种隔离级别下起作用。

MVCC 的实现形式通过两个暗藏列 trx_id(最近一次提交事务的 ID)和 roll_pointer(上个版本的地址),建设一个版本链。并在事务中读取的时候生成一个 ReadView(读视图),在 Read Committed 隔离级别下,每次读取都会生成一个读视图,而在 Repeatable Read 隔离级别下,只会在第一次读取时生成一个读视图。

InnoDB 如何解决幻读的?

先遍及一下快照读和以后读。

以后读: 读取数据的最新版本,并对数据进行加锁。

例如:insert、update、delete、select for update

快照读: 读取数据的历史版本,不对数据加锁。

例如:select

在以后读的状况下,是通过加锁来解决幻读。

在快照读的状况下,是通过 MVCC 来解决幻读。

面试官: 还得是你,就你总结的全。明天的面试先到这吧,下一面要问你 MySQL 的锁,你筹备一下。

本文知识点总结:

文章继续更新,能够微信搜一搜「一灯架构」第一工夫浏览更多技术干货。

正文完
 0