打死记不住的隔离级别,笨人需要多动笔,写个笔记先。
【原】=========> 巨人的肩膀
- Read uncommitted (读取未提交的内容)
一个事务可以看到其他事务未提交的处理结果。会导致脏读。 - Read committed
一个事务只可以看到其他事务提交的处理结果。大多数据库的默认隔离级别,但MySQL不是 - Repeatable read
保证一个事务中相同查询返回的结果一定是相同的,但是会有幻读的问题。是MySQL的默认隔离级别。 - Serializable
事务串行化,会出现大量超时、锁竞争。
潜在问题:
脏读:事务A读取了事务B未提交的处理结果,此时事务B回滚了操作,事务A读取到的就是错误的脏数据。
幻读:
实践检验:
查询当前会话事务隔离级别:
select @@transaction_isolation;
select @@transaction_isolation
(注:简书上传图片,直接修改连接后数字改变图片大小)
查看系统隔离级别:
select @@global.transaction_isolation
select @@global.transaction_isolation
开启两个会话A/B 修改隔离级别,然后模拟事务操作,在B中查询数据
修改当前会话隔离级别
set session transaction isolation level read uncommitted;
修改系统隔离级别
set global transaction isolation level read uncommitted;
设置隔离级别为read uncommitted(读未提交);
开启事务,更新数据,不提交
初始数据
开启事务,修改数据,不提交
会话B 查询已经可以看到修改结果
此时A rollback,B就读到了脏数据。
设置隔离级别为read committed(读已提交);
会话A 开启事务,修改数据,不提交
会话B 中查询,数据未更改
会话A commit
会话B查询,数据更改
read commited级别下,一个事务只可以访问到其他事务已经提交的更改,解决了脏读问题。但是会话B两次查询的结果不一致,所以read committed 级别可能导致在一个事务范围下,相同的查询可能出现不同的结果,就是不可重复读。
设置隔离级别为repeatable read(可重复读);
数据初始状态
开启事务,修改数据,不提交
会话B 开启事务,查询不到更新的数据
会话A commit
会话B 还是读不到更新的数据
这就解决了不可重复读的问题,保证了一个事务范围内,同一个查询返回的结果一样。
但是此时插入一条数据并提交
会话A 插入数据并提交
会话B 也读不到这条数据
会话B commit 结束此次事务后,才可以查询到会话A 更新和插入的数据
可重复读解决了不可重复读的问题,但是会有 幻读的问题。
设置隔离级别为Serializable(串行化)
会话B 开启事务,查询数据初始状态
会话A 会进入等待状态,因为会话B的事务没有提交
会话B commit
会话A 提交成功
时间太长就会超时