美文网首页Java成长之路
手撕 MySQL 事务,发生了什么?

手撕 MySQL 事务,发生了什么?

作者: 路人甲java | 来源:发表于2020-05-06 14:59 被阅读0次
image.png

什么是事务?
数据库事务( transaction)是访问并可能操作各种数据项的一个数据库操作序列,这些操作要么全部执行,要么全部不执行,是一个不可分割的工作单位。事务由开始和结束之间执行的全部数据库操作组成。

这是百科的定义,也是我们在面试的时候最常回答的关键字。

可以这么说:事务是数据库执行过程的一个逻辑单位,由一个有限的数据库操作序列组成。

举例来说,当我们购物下订单时,有这么两个操作(当然不止这俩):付款,减库存。这两个操作序列就是一个事务,他不能拆分执行,必须同时成功和失败。

当我们面试时最常遇到的问题是什么?
或者不那么世俗的说——毕竟我们学习并不全是为了面试嘛,啊呸!不面试谁看那么多,脑子内存本来就不大。


image.png

事务的4大特性

A (Atomicity) 原子性:事务的操作序列不可再拆分:这也是都成功都失败的意思。
C (Consistent) 一致性:事务的执行使数据从一个状态转换为另一个状态,但是对于整个数据的完整性保持稳定。
I(Isolation)隔离性:隔离性是当多个用户并发访问数据库时,比如操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离。
D(Durable)持久性:久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响。
关于ACID抢眼回答:

数据库的每一个操作其实是一条日志。

原子性,在 InnoDB 里面是通过 undo log 来实现的,它记录了数据修改之前的值(逻辑日志),一旦发生异常,就可以用 undo log 来实现回滚操作。

持久性怎么实现呢?数据库崩溃恢复(crash-safe)是通过什么实现的?

是通过 redo log 和 double write 双写缓冲来实现的,我们操作数据的时候,会先写到内存的buffer-pool中,同时记录 redo log,如果在刷盘之前出现异常,在重启后就可以读取 redo log 的内容,写入到磁盘,保证数据的持久性。

当然,恢复成功的前提是数据页本身没有被破坏,是完整的,如果数据页本身损坏了,这个可以通过双写缓冲 (double write)保证。

说了这么多事务,你甚至可能在实际编程中并没有手动操作过事务,那么如何手动开启和关闭事务呢?


image.png
image.png

Mysql数据库默认是开启自动提交事务的,也就是说当你执行update/delete/insert操作时数据库引擎会自动开启一个事务,并且在操作完成后自动提交事务。

事务并发产生的问题

脏读,读到了其他事务还没提交的数据
不可重复读,读到了其他事务提交之后的数据,数据变化了(update/delete)
幻读,读到了其他事务提交之后的数据,只有数据增加了行才叫幻读(insert)
你可能会说,事务不是有隔离性吗,为什么还有这么多问题?好了继续往下看

事务隔离级别

Read Uncommited 未提交读,顾名思义,可以读到其他事务没有提交的数据,会产生脏读
事务操作时并不隔离其他的事务,比如以下操作:


image.png

而如果此时事务1 回滚了事务,事务2就读到了脏数据;

这种隔离机制在数据库实际使用中,显然不合适,但有助于理解其他事务。

Read Commited 已提交读,只能读取其他事务已经提交的数据,不能读取到其他事务未提交的数据,它解决了脏读的问题, 但是会出现不可重复读的问题。
事务只能读取其他事务提交之后的数据,我们来模拟以下这个过程会出现的问题:


image.png

可以看到,这种隔离级别会导致数据在一个事务两次读取的数据不一致,也就是不可重复读;

Repeatable Read 可重复读,它解决了不可重复读的问题, 也就是在同一个事务里面多次读取同样的数据结果是一样的,但是在这个级别下,没有解决幻读的问题。
这也是最常用的事务隔离机制,他可以保证在一个事务里读取的数据是一样的,也就是数据的可重复读。你可能会问,数据库是如何实现可重复读的?这个问题会在之后解答,先来看看什么是幻读。

一个事务前后两次读取数据数据不一致,是由于其他事务插入数据造成的,这种情况我们把它叫做幻读。

比如:


image.png

第二次查询我们发现多了一条数据,这就叫幻读。需要记住的是只有其他事务插入导致的数据不一致才叫幻读。

Serializable(串行化),最后一个是串行的隔离级别,也是最严格的隔离级别,它要求事务必须排队执行,解决了幻读。但这大大影响了效率。也比较少用。
所以你会说,既然我们比较常用的是RR(可重复读)的隔离级别会有幻读的情况,那为什么还经常使用它?其实在MySQL的InnoDB引擎使用RR的隔离级别但配合锁的机制已经避免了幻读情况。

我们先来看一下MySQL是如何实现数据的可重复的。

有两种方案。

LBCC (Lock Based Concurrency Control),意思是读取数据的时候锁定它,不允许其他事务操作,数据自然也不会变化。这种方案我们叫做基于锁的并发控制简称LBCC。一个事务读取的时候不允许其他时候修改,那就意味着不支持并发的读写操作,而我们的大多数应用都是读多写少的,这样会极大地影响操作数据的效率。
MVCC (Multi Version Concurrency Control), 意思是多版本并发控制,另一种解决方案是如果要让一个事务前后两次读取的数据保持一致, 那么我们可以在修改数据的时候给它建立一个备份或者叫快照,后面再来的事务读取这个快照就行了。
MVCC的核心思想是:可以查到在当前事务开始之前已经存在的数据,即使它在后面被其他事务修改或者删除了。而当前事务之后新增的数据,当前事务是查不到的。

那么问题来了,如何保证当前事务数据的一致性呢?也就是说怎么保证数据被其他事务修改和删除或者新增了数据,而当前事务并不受影响呢?

读取数据事务开始的时候,MySQL为事务创建了快照,也就是在事务内查询的数据都是快照版本,这样就可以保证数据的一致性。

那么快照又是如何实现的呢?
InnoDB 为每行记录都实现了两个隐藏字段:

DB_TRX_ID,6 字节:插入或更新行的最后一个事务的事务ID,事务编号是自动递增的(我们把它理解为创建版本号,在数据新增或者修改为新数据的时候,记录当前事务ID)
DB_ROLL_PTR,7 字节:回滚指针(我们把它理解为删除版本号,数据被删除或记录为旧数据的时候,记录当前事务 ID)。
我们把这两个事务ID理解为版本号。

从插入数据开始,我们来看一下MySQL如何用这两个版本号来隔离事务。


image.png

此时又有一个事务进来,增加了一条数据并提交结束。


image.png
MVCC 的查找规则1:只能查找创建时间小于等于当前事务 ID 的数据
image.png

再次回到事务2查询


image.png
MVCC 的查找规则2: 能查找删除时间大于当前事务id的数据,也就是在事务之后删除的数据在当前事务依然能查得到。

事务5,尝试修改数据


image.png

此时回到事务2再次查询数据


image.png

按照查找规则:只能查找创建时间小于等于当前事务 ID 的数据,和删除时间大于当前事 务 ID 的行(或未删除)。

解释:id为1的数据删除版本大于当前事务2,创建版本小于事务2,依然可以查到,

id为2的数据创建版本为1的数据,小于事务2,删除版本大于事务2,可以查到

id为3的数据创建版本为3大于事务2,查不到;

id为2的数据创建版本为5的数据,大于事务2,依然查不到;

所以,在事务2内,无论外部发生了什么翻天覆地的变化,事务2自始自终查到的都是自己的快照数据,保证了数据的一致性,一定要理解MVCC的核心思想。

之后会更新结合锁机制,InnoDB是如何在RR级别解决幻读的。

相关文章

  • 手撕 MySQL 事务,发生了什么?

    什么是事务?数据库事务( transaction)是访问并可能操作各种数据项的一个数据库操作序列,这些操作要么全部...

  • Mysql 面试题

    1.什么Mysql的事务?事务的四大特性?事务带来的什么问题? Mysql中事务的隔离级别分为四大等级:读未提交(...

  • MySQL优化之事务基础,实战优化的基础知识

    MySQL的逻辑架构 MySQL主键自增机制 MySQL关键词 什么是事务 MySQL 创建事务的基础语法 一组事...

  • 7月13日 星期五 多云

    手撕面包 我爱吃手撕面包。 今天早上,爸爸问我想吃什么?我说:“我想吃手撕面包。...

  • 10-事务

    事务基础 什么是事务MySQL 中的事务主要用于处理操作量大,复杂度高的数据。MySQL 中只有使用了 Innod...

  • 想吃面包别出去买了,手把手教你做手撕包,香甜软糯,奶香浓郁

    手撕已经成为了中的一种常态,很多的是食品都有手撕版本,例如手撕牛肉,手撕豆腐干,手撕鸭,手撕鸡,手撕面包当然也有的...

  • 手撕鸡

    手撕鸡、手撕面包、手撕包菜、手撕牛肉,各种手撕做法,听起来就很手工的感觉。我做的手撕鸡纯粹懒人所为。 具体做法如下...

  • Mysql事务

    1) mysql事务的ACID特性 2)MySQL事务隔离级别

  • 收集几十位大厂面试者的面试题及个人见解-MySQL模块

    1.1 MySQL事务特性是什么?怎样实现ACID特性? MySQL事务指:一组操作要么同时成功要同时失败。所以事...

  • 美食十五-手撕鸡

    手撕鸡是一道家常菜,很难界定它的产地归属,手撕鸡有外皮金黄的盐焗鸡手撕,有风干鸡手撕,还有特色的手撕鸡丝。 手撕鸡...

网友评论

    本文标题:手撕 MySQL 事务,发生了什么?

    本文链接:https://www.haomeiwen.com/subject/pzkwghtx.html