MySQL 隔离性

2021/7/10 19:08:43

本文主要是介绍MySQL 隔离性,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

MySQL的结构

image

MySQL数据引擎 InnoDB 和 MyISam 的区别

事务方面

InnoDB 支持事务,而 MyISam 不支持事务。这个是 mysql 将默认引擎改为 InnoDB 的主要原因。

外键方面

InnoDB 支持外键,而 MyISaM 不支持外键

索引方面

InnoDB是聚簇索引,而 MyISam 是非聚簇索引

锁的粒度

InnoDB是行锁, MyISam是列锁,这也是把 myISAM 改成 InnoDB的一个重要原因

保存的文件格式

MyISAM 是有三个文件

  • .frm 存储表的定义

  • .myd 存的是数据

  • .myi 存的是索引

InnoDB 有两个文件(没有专门保存数据的文件)

  • .frm 表的定义

  • .idb 数据和索引存储文件

非聚簇索引。索引和数据是分开存的

image

聚簇索引,索引和数据是一起存的

image

所以也就明白了为什么尽量使用覆盖索引?

正如下图,如果使用覆盖索引,直接就把数据拿出来了,而不需要再去主键索引里去查找了

image

ACID

  • 原子性(atomicity)
  • 一致性(consistency)
  • 持久性(isolation)一行数据被删除了,还能回滚回来吗?显然不行
  • 隔离性(durability)

并发控制的时候,出现的三种问题

脏读

指当一个事务正在访问数据,并且对数据进行了修改,而这种数据还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据。因为这个数据还没有提交那么另外一个事务读取到的这个数据我们称之为脏数据。依据脏数据所做的操作肯能是不正确的。

不可重复读

不可重复读:指在一个事务内,多次读同一数据。在这个事务还没有执行结束,另外一个事务也访问该同一数据,那么在第一个事务中的两次读取数据之间,由于第二个事务的修改第一个事务两次读到的数据可能是不一样的,这样就发生了在一个事物内两次连续读到的数据是不一样的,这种情况被称为是不可重复读。

幻读

幻象读:一个事务先后读取一个范围的记录,但两次读取的纪录数不同,我们称之为幻象读(两次执行同一条 select 语句会出现不同的结果,第二次读会增加一数据行,并没有说这两次执行是在同一个事务中)

其实仔细想想,就脏读和不可重复读两种情况,幻读只不过是读多行的不可重复读

在标准的 SQL 规范中,事务的隔离级别有四种

读未提交

事务 A 和事务 B 同时执行,事务 A 在整个执行过程中,把数据从 1 加到 10 ,而事务 B可以看到事务 A操作的中间值。所有他会脏读

读已提交

示例:程序员拿着信用卡去享受生活(卡里当然是只有3.6万),当他埋单时(程序员事务开启),收费系统事先检测到他的卡里有3.6万,就在这个时候!!程序员的妻子要把钱全部转出充当家用,并提交。当收费系统准备扣款时,再检测卡里的金额,发现已经没钱了(第二次检测金额当然要等待妻子转出金额事务提交完)。程序员就会很郁闷,明明卡里是有钱的…

注意:

也就说,事务对数据进行 操作时,读操作事务要等待这个 操作事务提交后才能读取数据

可重复读

事例:程序员拿着信用卡去享受生活(卡里当然是只有3.6万),当他埋单时(事务开启,不允许其他事务的UPDATE修改操作),收费系统事先检测到他的卡里有3.6万。这个时候他的妻子不能转出金额了。接下来收费系统就可以扣款了。

注意:

重复读可以解决不可重复读问题。写到这里,应该明白的一点就是,不可重复读对应的是修改,即UPDATE操作。但是可能还会有幻读问题。因为幻读问题对应的是插入INSERT操作,而不是UPDATE操作。

串行化

是最严格的事务隔离级别,它要求所有事务被串行执行,即事务只能一个接一个的进行处理,不能并发执行。

总结一下这四种隔离级别

  • 为什么会出现“脏读”?因为没有“select”操作没有规矩。
  • 为什么会出现“不可重复读”?因为“update”操作没有规矩。
  • 为什么会出现“幻读”?因为“insert”和“delete”操作没有规矩。
  • “读未提(Read Uncommitted)”能预防啥?啥都预防不了。
  • “读提交(Read Committed)”能预防啥?使用“快照读(Snapshot Read)”,避免“脏读”,但是可能出现“不可重复读”和“幻读”。
  • “可重复读(Repeated Red)”能预防啥?使用“快照读(Snapshot Read)”,锁住被读取记录,避免出现“脏读”、“不可重复读”,但是可能出现“幻读”。
  • “串行化(Serializable)”能预防啥?排排坐,吃果果,有效避免“脏读”、“不可重复读”、“幻读”,不过效果谁用谁知道。

image

MySQL是如何保证 ACID的?

使用 Undolog 来实现原子性

原子的保证,其实就是依赖于 rollback 回滚机制,在sql语句执行的时候,就会记录 undo log 日志,当执行发生回滚的时候,mysql就会执行与 undo log 相反的操作,比如你之前执行了一个 create 操作,那么他就会执行一个 delete 操作,如果你执行了一个 updata 操作,那么mysql就执行一个相反的 updata 操作。

使用 redolog 来实现持久性

背景: 因为数据的写是写在磁盘中的,所以每次的 IO 操作都很费时间,所以 mysql 建立了一个缓存 buffer,每次把要提交的数据写到缓存的 buffer中,然后把buffer中的数据,一次性的写入到数据库中,问题就在于这个了。如果数据我写入到 buffer 中,但是 buffer 中的数据还没有写入磁片。此时数据库宕机了。

 解决这个问题,就是在将数据写入 buffer 的时候,同时将操作写入 redo log 中,因为redog是使用文件的追加模式的,所以他比将buffer写入磁盘要快很多很多。

隔离性

  • - :操作,通过锁来实现的
  • - :操作,通过 MVCC机制实现的

写写操作如何用锁实现

如果是 写-写 操作的话,可以使用,来实现,锁呢分为表锁,行锁,还有间隙锁。其具体的区别在另一篇博客中可见https://www.cnblogs.com/rush-peng/p/14992892.html

一致性

其实一致性是最终要追求的目标,就是通过上面的三种性质,来保证最终的数据库的一致性,比如主键唯一,数据要合法,在合理的范围内,等等。

什么是 MVCC

mvcc 全称 Multi-Version Concurrency Control ,即多版本并发控制。
同一行的数据,在执行读写操作的时候,会上 阻塞锁 ,但是 MVCC 在读写的时候,不用加锁

参考文献

https://www.cnblogs.com/myseries/p/10748912.html
https://www.jianshu.com/p/fc8a654f2205
乐观所和悲观锁



这篇关于MySQL 隔离性的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程