Code前端首页关于Code前端联系我们

学习并理解MySQL的4种事务隔离级别

terry 2年前 (2023-09-26) 阅读数 47 #数据库
MySQL的4种事务隔离级别学习与理解首先,创建表账户。跳过建表过程(由于InnoDB存储引擎支持事务,所以表的存储引擎设置为InnoDB)。表的结构如下: MySQL的4种事务隔离级别学习与理解 然后向表中插入两个条目。插入后的结果如下: MySQL的4种事务隔离级别学习与理解 为了说明问题,我们打开两个控制台,分别登录,模拟两个用户(现在是用户A和用户B),并设置当前MySQL会话的事务隔离级别。

1。 read uncommited data(读取未提交的数据)

用户A的具体操作如下:
set session transaction isolation level read uncommitted;
start transaction;
select * from account; 复制代码
结果如下: MySQL的4种事务隔离级别学习与理解用户B的操作如下:
set session transaction isolation level read uncommitted;
start transaction; 
update account set account=account+200 where id = 1;复制代码
然后我们查询数据在用户 A 中,结果如下: MySQL的4种事务隔离级别学习与理解

结论 1

我们将事务隔离级别设置为“未提交”。即使事务没有提交,我们仍然可以读取未提交的数据。这是所有绝缘水平中最低的

那么这有什么问题呢? 也就是说,我们可以在一个事务中直接读取其他事务的数据。这是相当困难的。我们称之为脏读。我不知道这个名字是怎么来的。为了增加大家的印象,可以这样想。这个问题太草率了。我太饿了,连别人没有提交的东西都等不及了。太恶心了,恶心!我们的数据真的改变了吗?答案是否定的,因为直到事务提交后它才会在数据库中更新。

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

同样,我们将用户B所在会话的当前事务隔离级别设置为读专用。在用户A所在的会话中,我们执行如下操作:
update account set account=account-200 where id=1;复制代码
MySQL的4种事务隔离级别学习与理解将id=1的用户帐号减200,然后查询,发现id=1的用户帐号已经变成了800。在用户B所在的会话中查询:
  1. select * from account;复制代码
结果如下:MySQL的4种事务隔离级别学习与理解我们会发现数据没有变化,还是1000。然后在会话A中我们提交交易:
  1. commit;复制代码
查询导致Session B如下: MySQL的4种事务隔离级别学习与理解

结论2:

如果我们将当前会话的隔离级别设置为commited read,则当前会话只能读。获取其他事务提交的数据,无法读取未提交的数据。

那么这样做有什么大不了的呢? 即我们在会话B中的同一个事务中读取到了两次不同的结果,这就导致了不可重复读,即两次读取的结果不同。这种现象称为不可重复读取。

3。可重复读(rereadable)---MySQL默认隔离级别

现在有一个问题,就是老大说同一个事务中查询结果要一致。如果你是数据库,你会做什么? ?这就是数据库的作用。在会话 B 中,我们当前的事务隔离级别是可重复的。具体操作如下:
set session transaction isolation level repeatable read;
start transaction;复制代码
然后查询会话B中的数据: MySQL的4种事务隔离级别学习与理解 我们在用户A的会话中的账户表中添加一条数据:
insert into account(id,account) value(3,1000);
commit;复制代码
然后查询数据是否已插入成功: MySQL的4种事务隔离级别学习与理解 回到 B 用户所在的会话,我们的搜索结果: MySQL的4种事务隔离级别学习与理解用户 B 想要在他所在的会话中插入一条 id=3、value=1000 的新数据。让我们开始吧:MySQL的4种事务隔离级别学习与理解

什么?无法插入,提示我的数据重复? 用户B当然不满意,因为搜索到的只有两条。为什么插入id=3时提示我的数据重复?我又看了一遍。难道是我眼花了? MySQL的4种事务隔离级别学习与理解想象一下,用户A和用户B实际上必须彼此隔离,并且不知道彼此在做什么。用户B如果遇到这种现象肯定会愤怒不已。当插入明显不存在的数据时,会提示主键数据id=3重复。

结论3:

如果我们将当前会话的隔离级别设置为可重复读,则当前会话可以重复读取,即每次读取结果都是一样的,无论其他事务是否有已承诺。

您还有什么问题吗? 总之,老板的要求达成了。事务中读取的数据必须一致(可重复读取)。我能做的就是假装自己很胖。数据已经改变,但我仍然想保持一致。然而,用户 B 遇到了一个问题。这种现象叫做幻读(我记得在这个地方纠结了很久,到底什么是幻读)。

4。 Serialized(序列化)

同样,我们将用户B所在会话的事务隔离级别设置为Serialized并启动事务。
set session transaction isolation level serializable;
start transaction;复制代码
在用户B所在的会话中,我们执行以下操作:
select * from account;复制代码
结果如下: MySQL的4种事务隔离级别学习与理解如果我们在用户A当前所在的会话中写入数据会怎样? MySQL的4种事务隔离级别学习与理解我们发现用户A所在的会话一直在等待。如果发生超时(该时间可以配置),则会出现“锁定等待时间”。提示:MySQL的4种事务隔离级别学习与理解如果用户B的会话交易在等待期间提交,用户A在写入交易时会提示操作成功。

结论4:

如果我们将当前会话的隔离级别设置为可序列化,则其他会话对该表的写入将被暂停。正如您所看到的,这是最严格的绝缘级别,但它不可避免地会影响性能。因此,在实际选择时,我们应该根据当前的具体情况来选择合适的。

作者:程序员追风
链接:https://juejin.im/post/5d8b2a9c518825091471fe2c
来源:掘金
版权归作者所有。商业转载请联系作者获得许可。非商业转载请注明出处。

版权声明

本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

热门