数据库库事务隔离级别是个什么玩意


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

1、数据库事务的特征 数据库

一、原子性 浏览器

原子,顾名思义,天然界中的最小粒子(尽管物理上原子还可分割成夸克的什么玩意,这个咱们就无论了)。定义一组操做集合,若是只执行一个子集,这就破坏的事务的目标,事务必须不可分割,要么所有执行,要么所有不执行。 安全

        二、一致性 session

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

三、隔离性 并发

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

        四、持久性 高并发

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

2、几个有趣的现象

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

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

一、脏读

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

这个过程当中,有两个事务在操做同一条数据:以下表,T表明时间

事务1

事务2

T1开启事务

 

 

T2开启事务

 

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

T4小明查到分数90

 

 

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

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

 

T7提交事务

  

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

二、不可重复读

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

事务1

事务2

T1事务开启

 

T2小明查到分数59

 

 

T3事务开启

 

T4修改分数为69

 

T5提交事务

T6小明打印成绩69

 

T7提交事务


三、幻读

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

事务1

事务2

       T1事务开启

 

T2小明查分,不包括英语

 

 

T3开启事务

 

T4英语老师录入分数

 

T5提交事务

T6小明打印到了英语成绩

 

T7提交事务

 

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

3、事务的隔离级别

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

事务隔离级别:

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

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

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

四、序列化(SERIABLIABLE)

隔离级别

脏读

不可重复读

幻读

READ-UNCOMMITTED

Y

Y

Y

READ-COMMITTED

N

Y

Y

REPEATABLE-READ

N

N

Y

SERIALIZABLE

N

N

N

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

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

一、脏读

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

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

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

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

(5)、B事务回滚

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

(7)、A事务提交;

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

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

(2)、A事务查询

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

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

(5)、B事务提交;

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

二、不可重复读

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

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

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

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

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

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

下面咱们看看REPEATABLE-READ,可否解决咱们的问题:

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

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

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

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

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

三、幻读

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

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

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

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

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

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

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

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

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

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

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

相关文章
相关标签/搜索