mysql事务隔离级别


四种隔离级别

我们愿意舍弃一部分隔离性来换取一部分性能在这里就体现在:设立一些隔离级别隔离级别越低并发问题发生的就越多。

SQL标准 中设立了4个 隔离级别 :

READ UNCOMMITTED :读未提交,在该隔离级别,所有事务都可以看到其他未提交事务的执行结果。不能避免脏读、不可重复读、幻读。

READ COMMITTED :读已提交,它满足了隔离的简单定义:一个事务只能看见已经提交事务所做的改变。这是大多数数据库系统的默认隔离级别(但不是MySQL默认的)。可以避免脏读,但不可重复读、幻读问题仍然存在。

REPEATABLE READ :可重复读,事务A在读到一条数据之后,此时事务B对该数据进行了修改并提交,那么事务A再读该数据,读到的还是原来的内容。可以避免脏读、不可重复读,但幻读问题仍然存在。这是MySQL的默认隔离级别。

SERIALIZABLE :可串行化,确保事务可以从一个表中读取相同的行。在这个事务持续期间,禁止其他事务对该表执行插入、更新和删除操作。所有的并发问题都可以避免,但性能十分低下。能避免脏读、不可重复读和幻读。

不可重复读问题

在读已提交的事务隔离级别并没有解决不可重复读的问题

测试

#设置事务隔离级别  设置为读已提交
SET  SESSION transaction_isolation ='READ-COMMITTED'


#查看事务隔离级别
SHOW VARIABLES LIKE 'transaction_isolation'

#在事务A中
begin
#此时查询到的数据是  测试
select  * from  student where id=1   


#在事务B中

begin
 
update  student set name='测试11'  where id=1

commit

#此时在事务A中读取到的数据是  
  测试11 
这时就发生了不可重复读的问题




#如果把事务隔离级别设置为  可重复读  就解决了可重复读的问题
SET  SESSION transaction_isolation ='REPEATABLE-READ'

https://www.zhihu.com/question/344692099 来自知乎一个回答

问题是既然MySQL有事物隔离性,那为什么还会产生脏读?

这个事情不能简单的一概而论,还得结合锁和MVCC相关的知识来分析
一个select操作

如果不加锁(普通的select等),称为快照读,读取的是MVCC版本链里的快照版本(至于读哪一版本的数据,就得看隔离级别了)

如果加了锁(如select for update等),称为当前读,读取的是最新版本(也就是别的事务提交的版本)

所以这样就很清晰了:

在事务隔离级别为读未提交的情况下,事务B读取到的可能是事务A未提交的存在于版本链里的数据,这样就是脏读了。

有人可能是数据不是加锁了吗,为啥还能读?

我读取的是版本链里的数据,你加锁是加在最新落库的数据表里的表记录,跟我有什么关系?

所以最终结果就很清楚了,并不是一级封锁协议不能避免度脏数据,想下面这两周情况就不会发生脏读:

1)在非读未提交(读已提交、可重复读、串行化)隔离别下,不会出现脏读

2)在select加锁的情况下,不管什么级别,也不会出现脏读


文章作者: 蛰伏
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 蛰伏 !
  目录