博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
数据库库事务隔离级别是个什么玩意
阅读量:6706 次
发布时间:2019-06-25

本文共 2462 字,大约阅读时间需要 8 分钟。

  hot3.png

一直很想对数据库事务做一点总结,今天终于静下心来小小的总结一下。

一、数据库事务的特征

1、原子性

原子,顾名思义,自然界中的最小粒子(尽管物理上原子还可分割成夸克的什么玩意,这个我们就不管了)。定义一组操作集合,如果只执行一个子集,这就破坏的事务的目标,事务必须不可分割,要么全部执行,要么全部不执行。

        2、一致性

在事务完成时,所有数据必须保持一致的状态。例如:张三给李四转账100,元,张三账号扣除了100,而李四账号却没有变化,这就违背了一致性。

3、隔离性

多用户操作同一条数据时,必须时相互隔离,以免A用户操作影响了B用户.。

        4、持久性

一个事务成功了,那么就必定持久化到磁盘了,就算断电了,下次重启,数据依然正确完好。

二、几个有趣的现象

很多时候,我们习惯这样描述我们的系统,高并发、分布式、集群等等,对于一个多用户、多线程的应用,不可避免的共同访问相同的资源,如果没有一套规则去约束这些操作,势必要出乱子,这就是我们要重点讨论的事务隔离。

我们先来看看几个有趣现象:

1、脏读

期末考过了半个月,小明正在急切的查分,一遍一遍的刷新着浏览器,数学分数怎么还没出来??碰巧数学老师在录入分数,刚好录到小明90分,提交请求,恰好小明刷新,90分,欣喜若狂。而此时数学老师发现录入错误,撤销了事务,小明再次查询,分数消失,小明此时是各种猜测。

这个过程中,有两个事务在操作同一条数据:如下表,T代表时间

事务1

事务2

T1开启事务

 

 

T2开启事务

 

T3数学老师开始录入分数90

T4小明查到分数90

 

 

T5老师发现录入错误回滚数据

T6小明忧伤的查不到分数了

 

T7提交事务

  

很明显,事务1读到了事务2未提交的数据。

2、不可重复读

最终小明查到了分数为59,伤心的要准备补考了,准备把成绩打印出来,发现打印出来的成绩是69,原来老师发现有道题目解题思路新颖,要额外给小明加10分。

事务1

事务2

T1事务开启

 

T2小明查到分数59

 

 

T3事务开启

 

T4修改分数为69

 

T5提交事务

T6小明打印成绩69

 

T7提交事务

3、幻读

小明一直在焦急的等待最后一门英语成绩,发现始终没有出来,便想把已经出来的成绩先打印,最后发现打印出来的有英语成绩。

事务1

事务2

       T1事务开启

 

T2小明查分,不包括英语

 

 

T3开启事务

 

T4英语老师录入分数

 

T5提交事务

T6小明打印到了英语成绩

 

T7提交事务

 

注:有人要问了,不可重复读和幻读,一个德行,有什么区别,不可重复读是读到了修改数据,幻读是读到了新增的数据,有又有什么不同呢,数据库的锁不一样,下次分享。

三、事务的隔离级别

以上的现象,不同的事务隔离级别,会产生对于的现象。

事务隔离级别:

1、读未提交(READ-UNCOMMITTED);

2、读已提交(READ-COMMITTED);

3、可重复读(REPEATABLE-READ);

4、序列化(SERIABLIABLE)

隔离级别

脏读

不可重复读

幻读

READ-UNCOMMITTED

Y

Y

Y

READ-COMMITTED

N

Y

Y

REPEATABLE-READ

N

N

Y

SERIALIZABLE

N

N

N

四、MySql的隔离级别和对应现象

Mysql默认的隔离级别是REPEATABLE-READ

1、脏读

(1)、设定数据库隔离级别为READ-UNCOMMITTED

20222115_Nnw5.jpg

(2)、A事务开启,查询,没查到数据;

20222116_lHub.jpg

(3)、B事务开启,修改分数,但不提交;

20222116_LbIK.jpg

(4)、A事务查询,小明查到了分数90

20222116_WGLT.jpg

(5)、B事务回滚

20222116_FIOI.jpg

(6)、A事务再次查询,已经查不到;

20222116_E3Iz.jpg

(7)、A事务提交;

20222116_zW8I.jpg

下面我们看把隔离级别设置成READ-COMMITTED能否解决这个问题。

(1)、设定隔离级别为READ-COMMITTED;;

20222116_wEjL.jpg

(2)、A事务查询

20222116_ltkL.jpg

(3)、B事务修改,但不提交;

20222116_YP0h.jpg

(4)、A事务再次查询,却查询不到;

20222116_MnDA.jpg

(5)、B事务提交;

20222116_IV5H.jpg

(6)、A事务再次查询,查询到了分数;

20222116_uL6K.jpg

2、不可重复读

紧接着上面的例子,上面的A事务还没结束。

(1)、B事务再次修改分数提交;

20222116_g1tw.jpg

(2)、A事务再次查询;

20222116_ZSjx.jpg

那么这个时候有同学要问了,如果B事务没有提交,有C事务来修改小明的分数会怎么样??下面我们就来看看:

20222116_Sc1q.jpg

很明显,C事务无法修改这条记录,这条记录已经被加锁。我们略过这个小插曲。

两次读取的数据不一样,这就是不可重复读。读到的是其他事务已提交的数据,这也是无可厚非,当然有些系统特别变态要求可重复读。

下面我们看看REPEATABLE-READ,能否解决我们的问题:

(1)、设定事务隔离级别为REPEATABLE-READ

20222116_Hvpf.jpg

(2)、A事务开启,读数据;

20222116_AYz5.jpg

(3)、B事务开启,修改数据,并提交;

20222116_KJRf.jpg

(4)、A事务再次查询,发现结果没变;

20222116_2vem.jpg

很明显,在REPEATABLE-READ级别下,A事务读取数据是完全不受其他事务影响的,这就解决了不可重复读的问题。

3、幻读

紧接着上面的例子,事务A再次查询,碰巧再次之前B事务新增了一条记录,英语成绩被录入进来。

(1)、B事务新增一条记录,并提交;

20222116_VZgi.jpg

(2)、A事务再次查询;

20222116_cGS0.jpg

这里有同学就要奇怪了,为什么没有查到英语成绩,理论上要出现幻读了,这是Why??

Mysql的可重复读的实现和其他数据库是有区别的,不会造成幻读,那么还是要说说幻读,幻读,就是同一个事务内,多次查询,读取到其他session 事务insert并已经提交的数据。

那么我们来看看最后一个隔离级别SERIALIZABLE

(1)、设置隔离级别为SERIALIZABLE

20222116_nW5c.jpg

(2)、B事务开启,新增记录,并不提交;

20222116_xXug.jpg

(3)、A事务开启事务查询;

20222116_bgEi.jpg

B事务没提交,A事务就阻塞,就连select也会阻塞,这就是串行化得名的原因,只能顺序执行,所有安全级别最高,性能最低。

至于JDBC与隔离级别,请听下回分解。

转载于:https://my.oschina.net/u/1778239/blog/508922

你可能感兴趣的文章
2017 Material design 第四章第二节《单位和尺寸》
查看>>
2017 Material design 第一章第三节《Material特性》
查看>>
第七章——字符串(代码点视图)
查看>>
如何合理布置React/Redux的目录结构
查看>>
nodejs随笔(一)
查看>>
产品经理基本功(PRD)|将交互、业务逻辑、需求字段撰入文档
查看>>
如何将webpack2项目升级到webpack3
查看>>
Kotlin网络库Fuel的设计之道
查看>>
几次面试后,我的一些思考和总结
查看>>
如何为团队潜规则明码标价
查看>>
React Native错误汇总(持续更新)
查看>>
RxJava2 实战知识梳理(14) 在 token 过期时,刷新过期 token 并重新发起请求
查看>>
EventBus从源码角度来谈谈设计原理
查看>>
HTTP权威指南
查看>>
iOS开发笔记(三):消息传递与转发机制
查看>>
ApacheCN 翻译活动进度公告 2019.2.25
查看>>
Python缓存技术
查看>>
Metal入门(使用Metal画一个三角形)
查看>>
浅谈 iOS 应用启动过程
查看>>
Clang 之旅—[翻译]添加自定义的 attribute
查看>>