MySql 的事务隔离级别

来源:互联网 发布:拼接控制器和矩阵区别 编辑:程序博客网 时间:2024/05/16 19:08

首先创建一个表account。创建表的过程略过。表的结构如下:

然后往表中插入两条数据,插入后结果如下:


定义两个事务:A用户 和 B用户。

一. read uncommitted(可以读取未提交数据)

A 执行如下操作:
set session transaction isolation level read uncommitted;start transaction;select * from account;
随后我们在A中查询数据,结果如下:



B执行如下操作:

set session transaction isolation level read uncommitted;start transaction;update account set account=account+200 where id = 1;
最后A用户查询结果:



结论:

我们将事务隔离级别设置为read uncommitted,即便是事务没有commit,但是我们仍然能读到未提交的数据,这是所有隔离级别中最低的一种。

那么这么做存在什么问题呢?

那就是我们在一个事务中可以随随便便读取到其他事务未提交的数据,这还是比较麻烦的,我们叫脏读。我不知道这个名字是怎么起的,为了增强大家的印象,可以这么想,这个事务好轻浮啊,饥渴到连别人没提交的东西都等不及,真脏,呸!

实际上我们的数据改变了吗?

答案是否定的,因为只有事务commit后才会更新到数据库。

二. read committed(可以读取其他事务提交的数据)---大多数数据库默认的隔离级别

同样的办法,我们将用户B所在的会话当前事务隔离级别设置为read commited。

在用户A所在的会话中我们执行下面操作:

update account set account=account-200 where id=1;



我们将id=1的用户account减200。然后查询,发现id=1的用户account变为800。

在B用户所在的会话中查询:

select * from account;

结果如下:


我们会发现数据并没有变,还是1000。

接着在会话A中我们将事务提交:

commit;
在会话B中查询结果如下:


结论二:

当我们将当前会话的隔离级别设置为read committed的时候,当前会话只能读取到其他事务提交的数据,未提交的数据读不到。

那么这么做有什么问题吗?

那就是我们在会话B同一个事务中,读取到两次不同的结果。这就造成了不可重复读,就是两次读取的结果不同。这种现象叫不可重复读

三. repeatable read(可重读)---MySQL默认的隔离级别

现在有个需求,就是老板说在同一个事务中查询结果必须保持一致,如果你是数据库,你会怎么做?数据库是这么做的。

在会话B中我们当前事务隔离级别为repeatable read。具体操作如下:


set session transaction isolation level repeatable read;start transaction;
接着在会话B中查询数据:
我们在A用户所在会话中为表account添加一条数据:
insert into account(id,account) value(3,1000);commit;
然后我们查询看数据插入是否成功:



回到B用户所在的会话,我们查询结果:



用户B在他所在的会话中想插入一条新数据id=3,value=1000。来我们操作下:



什么?竟然插不进去,说我数据重复?

用户B当然不服啊,因为查询到数据只有两条啊,为什么插入id=3说我数据重复了呢?

我再看一遍,莫非我眼花了?



试想一下,在实际中用户A和用户B肯定是相互隔离的,彼此不知道操作什么。用户B碰到这种现象,肯定会炸毛的啊,明明不存在的数据,插入却说主键id=3数据重复了。

结论三:

当我们将当前会话的隔离级别设置为repeatable read的时候,当前会话可以重复读,就是每次读取的结果集都相同,而不管其他事务有没有提交。

有什么问题吗?

管他呢,老板的要求满足了。要一个事务中读取的数据一致(可重复读)。我只能这么做啊,打肿脸装胖子。数据已经发生改变,但是我还是要保持一致。但是,出现了用户B面对的问题,这种现象叫幻读(记得当时就在这个地方纠结好久,到底什么是幻读啊)。

四. serializable(串行化)

同样,我们将用户B所在的会话的事务隔离级别设置为serializable并开启事务。

set session transaction isolation level serializable;start transaction;
结果如下:


读没有问题,那我们在用户A所在的会话中写数据呢?



我们发现用户A所在的会话陷入等待,如果超时(这个时间可以进行配置),会出现Lock wait time out提示:



如果在等待期间我们用户B所在的会话事务提交,那么用户A所在的事务的写操作将提示操作成功。

结论四:

当我们将当前会话的隔离级别设置为serializable的时候,其他会话对该表的写操作将被挂起。可以看到,这是隔离级别中最严格的,但是这样做势必对性能造成影响。所以在实际的选用上,我们要根据当前具体的情况选用合适的。



原文链接:http://www.jianshu.com/p/4e3edbedb9a8



1 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 一只眼睛磨的慌怎么办 5个月宝宝结膜炎怎么办 金毛眼屎多白色怎么办 金毛眼红有眼屎怎么办 狗狗眼睛上火了怎么办 狗上火了眼屎多怎么办 金毛走路扭腰怎么办 金毛流鼻涕微黄怎么办 狗狗下眼皮红了怎么办 金毛眼睛打肿了怎么办 金毛的眼睛红怎么办 眼睛干涩有红血丝怎么办 小孩子眼睛红有眼屎怎么办 狗狗的肉垫粗糙怎么办 狗狗眼睛变蓝色怎么办 脸被太阳晒伤了怎么办 皮肤晒伤红肿痒怎么办 3岁儿童频繁眨眼怎么办 狗狗的眼睛红肿怎么办 脸过敏发红怎么办不痒 上眼皮红肿痒是怎么办 眼睛痒了几天了怎么办 眼睛肿了还痒怎么办 孩子脸上有红血丝怎么办 脸上长了红血丝怎么办 指甲受创出血了怎么办 手指被挤压紫了怎么办 眼睛撞了有淤血怎么办 下眼底有小白点怎么办 狗的白眼球充血怎么办 眼球有出血点是怎么办 吃阿胶上火了该怎么办 胎儿胼胝体发育不良怎么办 鸡眼看到硬芯了怎么办 小脚趾起茧子疼怎么办 脚起老茧很痛怎么办 化疗后骨髓抑制严重怎么办 胃炎引起的胃胀怎么办 胃病胀肚子很鼓怎么办 小孩淋巴结发炎肚子疼痛怎么办 顺产后子宫脱垂怎么办