Mysql17——事务隔离级别

隔离级别

事务隔离级别是数据库管理系统提供的一种机制,用于控制并发事务之间的相互影响程度。以下是四个标准的事务隔离级别:

  1. 读未提交(Read Uncommitted):在这个隔离级别下,一个事务可以读取其他事务尚未提交的数据。这种隔离级别最低,可能导致脏读、不可重复读和幻读等问题。
  2. 读已提交(Read Committed):在这个隔离级别下,一个事务只能读取并发事务已经提交的数据。这样可以避免脏读的问题,但仍然可能出现不可重复读和幻读。
  3. 可重复读(Repeatable Read):在这个隔离级别下,一个事务在执行期间多次读取同一数据将始终得到相同的结果。在该事务执行期间,其他事务对该数据所做的更改将被阻塞,以避免不可重复读的问题,但仍可能出现幻读。
  4. 串行化(Serializable):在这个隔离级别下,数据库系统确保每个事务的执行都彼此串行进行。这是最高的隔离级别,可以避免脏读、不可重复读和幻读。但是,由于串行执行,可能导致并发性能下降。

不同的隔离级别在保证数据一致性和并发性能之间做出了权衡。较低的隔离级别提供更高的并发性能,但可能导致更多的并发问题。较高的隔离级别提供更强的数据一致性,但可能降低并发性能。根据应用场景和对数据一致性要求的程度,可以选择适当的隔离级别。

一个事务与其他事务隔离的程度称为隔离级别。数据库规定了多种事务隔离级别,不同隔离级别对应不同的干扰程度,隔离级别越高,数据一致性就越好,但并发性就越差。

这里通过一个例子向大家简单介绍一下并发:

一个人在边开车 边打电话,首先,人只有一个大脑(cpu),但是在同一时刻他却在执行2件事情,其实内部就是靠他的大脑在不断的切换执行,之所以人民警察不允许司机开车时打电话,就是怕人脑在那一瞬间切换不过来,从而导致交通事故的发生,并发和这个例子是差不多的意思。但在这里,电脑cpu可比人脑快多了,所以出错的概率也相对来说小很多。

接一下,演示一下在几种不同的事务隔离级别下所发生的不同情况 。

在演示之前呢,还需要知道如何查看和设置事务的隔离级别

查看当前的事务隔离级别通过 tx_isolation变量或者transaction_isolation(版本8.0以上使用);

语法:select @@tx_isolation;

注意:在mysql8.0之后,就已经抛弃了tx_isolation变量了,而是用 transaction_isolation变量代替了。

语法:select @@transaction_isolation;
#设置当前mysql连接的隔离级别:
set session transaction isolation level read uncommitted;
#设置数据库系统的全局的隔离级别:
set global transaction isolation level read uncommitted;

注意:当前mysql连接的隔离级别和mysql全局的隔离级别的区别是什么?

如果只设置当前的隔离级别,也就是session,那么另外一个并发的“mysqy程序”的隔离级别不会受到当前连接的影响,而是保持默认的repeatable read。

但是如果是设置全局的事务隔离级别,则整个mysql数据库(包括所有打开的mysql程序连接)的隔离级别都会随之改变,除非服务器重启,不然就不会恢复默认了。

两者仅仅一词之差,其效果却天差地别

read uncommitted(读未提交)

首先,我们需要先将两个会话的事务隔离级别都设置为read uncommitted;语句如下:

set session transaction isolation level read uncommitted; 
#设置当前会话的隔离级别为read uncommitted

read uncommitted可以读到其他事务还没提交的变更,这里举例:程序2对t_account表中的数据进行更改,看程序1多次查询的结果是否一致。

在这里插入图片描述

可以看到程序2改变了t_account表中的vname字段,将李二改为了张三。但是程序1呢,连续2个select查询语句的结果竟然不一致,估计现在程序1的表情和你手机里的第三个表情包一样。这就是read uncommitted隔离级别的特点。
不管你事务是否提交,只要数据发生改变我就可以察觉到…嘻嘻。是不是感觉它很强大。什么事情都逃不过它的法眼。

接下来要看的是read committed(读已提交)

read committed(读已提交)

测试前一定要记住设置事务的隔离级别为read committed;并且禁用自动提交事务【设置autocommit为0】(后面的每个测试都是一样的)

# 设置事务隔离级别为read committed
set session transaction isolation level read committed;
# 禁用自动提交事务功能
set autocommit = 0; 
#接下来的 repeatable read 隔离级别和 serializable 隔离级别也是同样的操作

在这里插入图片描述

以上例子实现了王五为张三转账的事务,可以看到程序2中事务提交前与提交后对程序1中的查询语句产生的影响,前2个查询是事务没提交的结果,最后一个查询是事务提交后的结果。 相信上面的例子已经很充分的诠释了read committed的特点。

repeatable read(可重复读)

该隔离级别为mysql的默认隔离级别;它对某字段进行操作时,其他事务禁止操作该字段。它总能保持你读取的数据是一致的。

以下代码中,程序1模拟"王五向张三转账30元",程序2则在程序1在处理事务时,对张三的余额进行清空处理

在这里插入图片描述

因为当前的事务隔离级别为repeatable read级别,所以在程序1操作t_account表时,程序2是无权对t_account表进行任何操作,如果强行操作的话,就会发生error (错误)

“ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction”;

其中文意思是:“超过锁定等待超时;尝试重新启动事务”

只有当程序1对t_account表操作完成后(结束事务后),程序2才可以对t_account表进行操作。

在这里插入图片描述

serializable(串行化)

该隔离模式下执行的事务在对某表进行操作期间,禁止其他所有事务对该表进行任何操作

如果强行操作也会报错(和上面那个错误一致),因为serializable用的相对比较少,这里就不做演示了。同学们理解了就好。

事务的保存点(回滚点)

回滚点表示的就是使事务回滚到指定回滚点

语法: savepoint 节点名称 ;

注意:保存点只允许搭配rollback回滚来使用,不能和commit一起使用

已知表t_stu存在,其数据如下:

在这里插入图片描述

代码举例如下:

 #禁用自动提交事务
set autocommit = 0;
 #开启事务
start transaction;
 #删除id为2的记录
delete from t_stu where id = 2;
 #设置保存点名为AA
savepoint AA;
 #删除id为3的记录
delete from t_stu where id = 3;
  #回滚到AA保存点处
rollback to AA;

运行结果如下:

在这里插入图片描述

``

可以看到id为2的李四被删除了,而王五却还在,就是因为事务回滚到了AA处,所以id为3的那条记录被回滚掉了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值