四大隔离级别:
Read uncommitted:---不防止任何隔离型问题,不能防止脏读/不可重复读/幻读问题。
Read commit:---可以防止脏读问题,但是不能防止 不可重复读/幻读问题。(oracle默认隔离级别)
Repeatable read:---可以防止脏读/不可重复读,不能防止幻读。(mysql默认隔离级别)
Serializable:--数据库被设计为单线程,可以防止上述所有问题
脏读:一个事务读取到另一个事务未提交的数据。
场景:a账户1000,b账户1000,a到b的网店里买一百块钱的鞋子。。。。
a:start transaction
update table set money=money-100 where name='a';//a账户扣除100
update table set money=money+100 where name='b';//b账户增加100
此时a还没有提交事务,对b说付款成功
b:start transaction;//b开始查询自己的账户余额
select money form table where name='b';
b:commit;
如果读取到了a没有提交的数据,那么b查出来的就会是1100,此时b开始发货
此时a执行回滚
a:rollback;
那么b再去查询账户余额会发现自己的账户还是原先的100块
不可重复读:在当前事务中,读取到了另一事务提交的更新和删除的数据。
场景:如果a有活期资金1000,定期1000,固定资产1000
a: 1000 1000 1000
b: 银行职员,银行让职员b算出a客户的总共资产
---------
b:start transaction;
select 活期存款 from account where name='a'; ---- 活期存款:1000
select 定期存款 from account where name='a'; ---- 定期存款:1000
select 固定资产 from account where name='a'; ---- 固定资产:1000
-------此时a客户取走了自己活期的1000元
a:
start transaction;
update accounset set 活期=活期-1000 where name='a';
commit;
-------
select 活期+定期+固定 from account where name='a'; --- 总资产:2000,按照之前查出来的应该是3000元,但是现在是2000元
commit;
----------
但是虽然在这种场景下,出现了不可重复读,但是如果在另一场景下,如果你和你的伙伴共用一个银行账户共100万,你的伙伴如果中途取走了50万,而你此时读取到剩下的50万,就符合该场景。
幻读:在当前事务中,读取到了另一事务提交的插入的数据
场景:如果银行现在有a、b两位客户存款各1000,银行老板让职员b去算平均每个客户的平均存款,而又有新增客户c存入了4000元。
a: 1000
b: 1000
d: 银行业务人员
-----------
d:
start transaction;
select sum(money) from account; --- 2000 元
select count(name) from account; --- 2 个
------
c:
start transaction;
insert into account values(c,4000);
commit;
------
select sum(money)/count(name) from account; --- 平均:2000元/个,结果应该是平均存款1000,而实际结果却是2000
commit;
------------
https://www.shiyanlou.com/courses/1152/learning/?id=8064
可串行化
最高的隔离级别。
在基于锁机制并发控制的 DBMS 实现可串行化,要求在选定对象上的读锁和写锁保持直到事务结束后才能释放。在 SELECT 的查询中使用一个“WHERE”子句来描述一个范围时应该获得一个“范围锁”(range-locks)。这种机制可以避免“幻影读”(phantom reads)现象(详见下文)。
当采用不基于锁的并发控制时不用获取锁。但当系统探测到几个并发事务有“写冲突”的时候,只有其中一个是允许提交的。这种机制的详细描述见“快照隔离”
可重复读
在可重复读(REPEATABLE READS)隔离级别中,基于锁机制并发控制的 DBMS 需要对选定对象的读锁(read locks)和写锁(write locks)一直保持到事务结束,但不要求“范围锁”,因此可能会发生“幻影读”。
提交读
在提交读(READ COMMITTED)级别中,基于锁机制并发控制的 DBMS 需要对选定对象的写锁一直保持到事务结束,但是读锁在 SELECT 操作完成后马上释放(因此“不可重复读”现象可能会发生,见下面描述)。和前一种隔离级别一样,也不要求“范围锁”。
未提交读
未提交读(READ UNCOMMITTED)是最低的隔离级别。允许“脏读”(dirty reads),事务可以看到其他事务“尚未提交”的修改。
-----来自 wiki 百科
- 脏读:一个事务读取到了另一个事务没有提交的事务
- 不可重复读:一个事务中对同一行记录读取两次得到不同的结果
- 幻影读:一个事务两个相同的查询获得的结果不相同
不可重复读和幻影读的区别主要在于不可重复读是由于更新和删除操作造成的,而幻影读是由于插入操作造成的。