首页 > 编程知识 正文

数据库有几种隔离级别(MySQL数据库的隔离级别)

时间:2023-05-06 09:14:38 阅读:92688 作者:240

如果您对mysql性能调优感兴趣,请参阅详细的视频集合mysql调优系列

这次,我们来总结一下数据库的ACID是指什么。

原子性(atomicity)

是指事务是不可分割的工作单位,其中的操作是全部执行还是不全部执行。 也就是说处于转账成功、转账失败,不存在中间的状态!

如果不能保证原子性会怎么样?

发生数据不一致,从a账户减去50元,从b账户增加50元的操作失败。 系统会无缘无故损失50元。

一致性(consistency)

一致性是指在执行事务前后,数据处于语义状态而不是语法状态。 那么,什么是合法的数据状态呢? 这种状态,满足预定的限制就称为合法状态。 更简单地说,这种状态由你自己定义。 如果满足这个状态,数据就会匹配。 如果不满足这个状态,数据就不一致

如果不能保证一致性会怎么样? 一例:A账户200元,转账300元走人。 这时,a账户的余额为-100元。 此时自然发现数据不一致。 为什么会这样呢? 因为您定义了状态,所以余额列必须大于0。 例:A账户200元,转入b账户50元,a账户的钱被扣款,但b账户因各种事故余额没有增加。 我也知道这个时候数据不一致。 为什么会这样呢? 因为你定义了A B的余额必须变化的状态。

隔离性 (isolation)

独立性意味着在同时执行多个事务时,事务中的操作将与其他事务分离,并且同时执行的事务之间不会相互干扰。 如果不能保证隔离性会怎么样? 假设a账户有200元,b账户有0元。 a账户转入b账户两次,金额50元,分别在两个事务中执行。 如果隔离性得不到保证,就会出现以下情况

如图所示,如果不保证隔离性,a扣2次,b只扣1次,凭空消失50元,仍然发生数据不一致

持久性 (durability)

持久性意味着提交事务后,对数据库的更改将是持久性的。 之后的其他操作和故障请勿对其产生任何影响。

如果不能保证持久性会怎么样? 在Mysql中,为了解决CPU和磁盘速度的不一致问题,Mysql会将磁盘上的数据加载到内存中,操作内存,然后返回写入磁盘。 是的,假设此时停机了。 如果内存中所有修改的数据都丢失了,则不能保证持久性。

假设系统暗示转账成功了。 但是,我发现金额没有什么变化。 此时,数据发生了不正确的数据状态。 我认为这个状态是数据的不一致。

让我们聚焦于隔离级别!

隔离级别

在数据较高时可能会发生脏读取、不可重复读取、幻像读取等问题。

1 .脏领导:

脏读取是指,如果一个事务处理正在访问数据,对数据进行了更改,并且该更改尚未提交到数据库,则另一个事务处理也将访问该数据并使用该数据。

2 .不可重复阅读:

就是在一个交易内,多次读取同一数据。 在此事务还没有完成的同时,另一个事务也会访问相同的数据。 在中,第一个事务处理的第二个读取数据之间的第二个事务处理发生了改变,因此第一个事务处理第二个读取的数据可能不同。 这样,在一个事务内读取的数据会发生不同的情况,称为无法重复读取。 (即,不能读取相同的数据内容)

例如,假设一个编辑两次导入同一文档,但在两次导入期间作者改写了该文档。 编辑第二次载入文件时,文件已变更。 的读取不能重复。 如果编辑只能在所有作者都完成创建后读取文档,则可以避免此问题。

3 .幻读:

事务没有独立执行时发生的现象。 例如,第一个事务更改表中的数据,而该更改包含表中的所有数据行。 第二个事务还通过在表中插入新行来修改此表中的数据。 然后,正在处理第一个事务的用户注意到表中有未更改的数据行,就像产生了幻觉一样。

例如,如果某个编辑更改了作者提交的文档,生产部门将该更改合并到文档的主副本中,则可以看到作者向文档中添加了未编辑的新资料。 如果在编辑和生产部门完成原始文档的处理之前,没有人可以将新文档添加到文档中,则可以避免此问题。

数据库为防止以上问题提出了隔离级别的概念:从低到高依次为Read uncommitted、Read committed、Repeatable read、Serializable

>下面,我们来举例理解下以上四种隔离级别。

Read uncommitted 读未提交

公司发工资了,领导把5000元打到singo的账号上,但是该事务并未提交,而singo正好去查看账户,发现工资已经到账,是5000元整,非常高 兴。可是不幸的是,领导发现发给singo的工资金额不对,是2000元,于是迅速回滚了事务,修改金额后,将事务提交,最后singo实际的工资只有 2000元,singo空欢喜一场。

出现上述情况,即我们所说的脏读 ,两个并发的事务,“事务A:领导给singo发工资”、“事务B:singo查询工资账户”,事务B读取了事务A尚未提交的数据。

当隔离级别设置为Read uncommitted 时,就可能出现脏读,如何避免脏读,请看下一个隔离级别。

Read committed 读已提交

singo拿着工资卡去消费,系统读取到卡里确实有2000元,而此时她的老婆也正好在网上转账,把singo工资卡的2000元转到另一账户,并在 singo之前提交了事务,当singo扣款时,系统检查到singo的工资卡已经没有钱,扣款失败,singo十分纳闷,明明卡里有钱,为 何......

出现上述情况,即我们所说的不可重复读 ,两个并发的事务,“事务A:singo消费”、“事务B:singo的老婆网上转账”,事务A事先读取了数据,事务B紧接了更新了数据,并提交了事务,而事务A再次读取该数据时,数据已经发生了改变。

当隔离级别设置为Read committed 时,避免了脏读,但是可能会造成不可重复读。

大多数数据库的默认级别就是Read committed,比如Sql Server , Oracle。如何解决不可重复读这一问题,请看下一个隔离级别。

Repeatable read 重复读

当隔离级别设置为Repeatable read 时,可以避免不可重复读。当singo拿着工资卡去消费时,一旦系统开始读取工资卡信息(即事务开始),singo的老婆就不可能对该记录进行修改,也就是singo的老婆不能在此时转账。

虽然Repeatable read避免了不可重复读,但还有可能出现幻读 。

singo的老婆工作在银行部门,她时常通过银行内部系统查看singo的信用卡消费记录。有一天,她正在查询到singo当月信用卡的总消费金额 (select sum(amount) from transaction where month = 本月)为80元,而singo此时正好在外面胡吃zydds后在收银台买单,消费1000元,即新增了一条1000元的消费记录(insert transaction ... ),并提交了事务,随后singo的老婆将singo当月信用卡消费的明细打印到A4纸上,却发现消费总额为1080元,singo的老婆很诧异,以为出 现了幻觉,幻读就这样产生了。

注:MySQL的默认隔离级别就是Repeatable read。

Serializable 序列化

Serializable 是最高的事务隔离级别,同时代价也花费最高,性能很低,一般很少使用,在该级别下,事务顺序执行,不仅可以避免脏读、不可重复读,还避免了幻像读。

不断分享开发过程用到的技术和面试经常被问到的问题,如果您也对IT技术比较感兴趣可以「关注」我

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。