mysql数据隔离级别

mysql数据隔离级别

前置条件

mysql版本:8.0
为了方便分析问题,先在mysql中创建表并插入数据。
创表语句

CREATE TABLE `t` (
   `id` int NOT NULL AUTO_INCREMENT,
   `age` varchar(45) DEFAULT NULL,
   `name` varchar(45) DEFAULT NULL,
   PRIMARY KEY (`id`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci

并向其中添加数据

INSERT INTO `test`.`t` (`age`, `name`) VALUES ('1', '1岁大聪明');
INSERT INTO `test`.`t` (`age`, `name`) VALUES ('2', '2岁大聪明');
INSERT INTO `test`.`t` (`age`, `name`) VALUES ('3', '3岁大聪明');

读未提交(READ_UNCOMMITTED)

 事务中的修改,即使没有提交,对其它事务也是可见的。在mysql中可以通过select @@transaction_isolation来查询隔离级别。通过指令将数据库隔离级别修改为READ_UNCOMMITTED。

set global transaction isolation level READ UNCOMMITTED

 读未提交会导致的问题:脏读 不可重复读 幻读

脏读

 脏读就是指当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据。
 分别开启a和b两个事务,a先查询id=2这行数据,b更新id=2这行数据。
开启a事务

开启a事务并进行查询

开启b事务并修改数据

开启b事务并修改数据

 b事务修改数据之后并未提交,在这之后a事务在查询id=2这一行的数据。
在这里插入图片描述

a事务再次进行查询
 此时,在a事务中可以查询到未提交的b事务修改后的数据。

 可能导致的问题:若此时b事务进行了回滚,a读出的数据就是一个脏数据。

读已提交(READ_COMMITTED)

 一个事务只能读取已经提交的事务所做的修改。换句话说,一个事务所做的修改在提交之前对其它事务是不可见的。在读已提交的隔离级别下,并不会导致脏读,但是会导致不可重复读和幻读通过指令将mysql的隔离级别修改为读已提交。

set global transaction isolation level READ COMMITTED

不可重复读

 是指在一个事务内,多次读同一数据。在这个事务还没有结束时,另外一个事务也访问该同一数据。那么,在第一个事务中的两次读数据之间,由于第二个事务的修改,那么第一个事务两次读到的的数据可能是不一样的。这样就发生了在一个事务内两次读到的数据是不一样的,因此称为是不可重复读

 分别开始a事务和b事务,a事务查询id=2这一行的数据,b事务修改这一行的数据并提交。
开启a事务

开启a事务

开启b事务并进行提交

开启b事务并提交

 b事务提交之后,在a事务中查询数据,结果如下
a事务再次查询

a事务再次查询

 可以发现,在a事务中查询到了提交后的b事务修改之后的数据。在一个事务中前后两次读取的结果并不致,导致了不可重复读。
可能导致的问题: 一个刷卡的场景吧,要付100块钱,你在一个事务里,select了一下某个帐号,发现它的余额100元足够,于是发起减余额的操作,做update XX set 余额=余额-100 where …,结果在你update之前其它事务操作余额变成50了,update完变成-50了

可重复读(REPEATABLE_READ)

 保证在同一个事务中多次读取同一数据的结果是一样的。可重复读也是mysql默认的隔离级别。

幻读

 幻读本质上也属于不可重复读的情况,T1 读取某个范围的数据,T2 在这个范围内插入新的数据,T1 再次读取这个范围的数据,此时读取的结果和和第一次读取的结果不同。

Session ASession B
begin
select * from t where age = 2; T1begin
insert into t(age,name) values (2,‘第二个2岁大聪明’);
select * from t where age = 2; T2
commit
select * from t where age = 2; T3
update t set name=‘现在都是2岁大聪明’ where age =2;
select * from t where age = 2; T4

 不同时刻返回的数据分别为

  • T1   (1,2,2岁大聪明)
  • T2   (1,2,2岁大聪明)
  • T3   (1,2,2岁大聪明)
  • T4   (1,2,现在都是2岁大聪明)和(4,2,现在都是2岁大聪明)

 T3时刻到T4时刻,两次查询不一样。被称为“幻读”。也就是说,幻读指的是一个事务在前后两次查询同一个范围的时候,后一次查询看到了前一次查询没有看到的行。

 可重复读隔离级别可能会导致幻读的问题,但Innodb在可重复读隔离级别下解决了幻读(日后完善)。

可串行化(SERIALIZABLE)

 强制事务串行执行,这样多个事务互不干扰,不会出现并发一致性问题。

 该隔离级别需要加锁实现,因为要使用加锁机制保证同一时间只有一个事务执行,也就是保证事务串行执行。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值