Mysql 事务隔离级别

什么是事务

事务(Transaction)是并发控制的基本单位。所谓事务,它是一个操作序列,这些操作要么都执行,要么都不执行,它是一个不可分割的工作单位。例如,银行转帐工作:从一个帐号扣款并使另一个帐号增款,这两个操作要么都执行,要么都不执行。所以,应该把他们看成一个事务。事务是数据库维护数据一致性的单位,在每个事务结束时,都能保持数据一致性。

事务的4大特性:

  • 原子性:一个事务必须视为一个不可分割的最小工作单元,整个事务中的所有操作要么全部提交成功,要么全部失败回滚,对于一个事务来说,不可能只执行其中的一部分操作,这就是事务的原子性
  • 一致性:一个事务应该把系统从一个一致状态转换到另一个一致状态,例如上述银行转账例子,不管转账业务如何复杂,钱的总数是不变的
  • 隔离性:一个事务所做的修改在最终提交以前,对其他事务是不可见的
  • 持久性:一旦事务提交,则其所做的修改就会永久保存到数据库中。此时即使系统崩溃,修改的数据也不会丢失

隔离级别

MySQL是一个服务器/客户端架构的软件,对于同一个服务器来说,可以有若干个客户端与之连接,每个客户端与服务器连接上之后,就可以称之为一个会话(Session)。我们可以同时在不同的会话里输入各种语句,这些语句可以作为事务的一部分进行处理。不同的会话可以同时发送请求,也就是说服务器可能同时在处理多个事务,这样子就会导致不同的事务可能同时访问到相同的记录。事务的隔离性指理论上在某个事务对某个数据进行访问时,其他事务应该进行排队,当该事务提交之后,其他事务才可以继续访问这个数据。但是这样子的话对性能影响太大,所以在设计数据库时划分出多种隔离级别,来最大限度的提升系统并发处理事务的能力,但是这也是以牺牲一定的隔离性来达到的。

事务主要有4种隔离级别:

  • Read uncommitted (读取未提交)
  • Read committed (已提交读)
  • Repeatable read (可重复读)
  • Serializable (可串行化)

在我们通过示例演示之前我们先得了解另外三个名词:

  • 脏读:A 事务,会读取到 B 事务还未提交的数据。因为 B 事务可能会因为各种原因数据回滚,所以如果 A 事务读取了 B 事务未提交的数据,然后基于此进行一些业务操作,但是 B 事务发生错误回滚了,那 A 事务的业务操作就错了
  • 不可重复读:在 A 事务生命周期内,也就是 A 事务还未提交之前,如果另外一个 B 事务,对数据进行了编辑(update)或者删除(delete)操作(并且已提交),那么 A 事务再次读取发现数据不一致。简单理解,就是在一个事务生命周期内,多次查询数据,每次都可能查出来的不一样
  • 幻读:幻读的结果其实和不可重复读是一样的表现,差异就在于,不可重复读,主要是针对其他事务进行了编辑(update)和删除(delete)操作。而幻读主要是针对插入(insert)操作,也就是在一个事务生命周期内,会查询到另外一个事务新插入的数据。

我们先把结论结论摆出来,各隔离级别会出现结果:

隔离级别脏读不可重复读幻读
未提交读可能可能可能
已提交读不可能可能可能
可重复读不可能不可能可能
可串行化不可能不可能不可能

下面来演示 Mysql Innodb 中各隔离级别具体会出现什么样的结果

首先我们在数据库中新建一张 user 表,插入两条简单数据,并打开两个不同的查询窗口,结果如下:
在这里插入图片描述
在两个查询窗口中我们可以查询当前数据库和各自会话的隔离级别:

SELECT @@global.tx_isolation; //查询全局事务的隔离级别
SELECT @@session.tx_isolation; //查询当前会话的格力级别

查询出来的结果肯定是:REPEATABLE-READ,这是 mysql 的默认隔离级别


演示 Read uncommitted

我们将两个会话事务设置为:Read uncommitted(不需要设置全局隔离级别)

SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;

我们在第一个查询窗口(后续简称A窗口)中开始事务并插入一条数据,但是不提交,然后在第二个查询窗口(后续简称B窗口)中进行数据查询,如下:
在这里插入图片描述
可以看到,我们在 A 窗口中并未提交插入的数据,但是我们在 B 窗口中却能查询到,这就是 脏读

演示 Read committed

我们将两个会话事务设置为:Read committed

SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;

删掉“王五”这条数据并重复上述步骤,并未发生脏读现象
在这里插入图片描述
接着我们测试看看会不会出现 不可重复读 现象

先将上面测试脏读的数据提交,那么数据库中就有三条数据。接着在 A 窗口中重新开启事务,查询结果肯定是有三条数据存在,接着我们在 B 窗口中将 王五 修改成 五哥 并提交,接着在 A 窗口中查询,显示如下:
在这里插入图片描述
这意味着在 A 窗口同一个事务中查询两次数据库,查询的结果不一致。这就是不可重复读现象,当谈幻读现象也存在:
在这里插入图片描述

演示 Repeatable read

我们将两个会话事务设置为:Repeatable read

SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;

将数据重置为原先的那三条数据,按原来的步骤测试 不可重复读 现象,如下:
在这里插入图片描述
接着我们测试幻读现象:
在这里插入图片描述
mysql 在 5.6版本后,Repeatable read 隔离级别已经解决了幻读现象

Serializable

Serializable 完全串行化的读,每次读都需要获得表级共享锁,读写相互会相互互斥,这样可以更好的解决数据一致性的问题,但是同样会大大的降低数据库的实际吞吐性能。所以该隔离级别因为损耗太大,一般很少在开发中使用。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值