事务隔离级别

 

一, 事务的四大特性( ACID )

1, 原子性(Atomicity):事务执行前与事务执行后,数据库的状态应该是一致的。

2, 一致性(Consistency):事务执行前与事务执行后,数据库的状态应该是一致的。

3, 隔离性(Isolation):如果同时有多个事务在数据库中执行,事务与事务之间应该互不影响。

4,持久性(Durability) :事务一旦提交,对数据库的影响是持久的,就算关闭服务器,数据也是持久存在。

二, 对事务一致性的理解

如果不使用事务,那么在数据库执行多条语句的时候,有可能中间会出现问题而导致只执行了部分语句,因此,我们在这多条语句前面加上begin transaction,最后加上end transaction,这就是很清楚的标明了,在这些语句执行前,系统是处于一致性状态的,而在这些语句执行后,系统也是处于一致性状态的,至于这个一致性状态的定义,则是由用户通过这些语句来表达的。那么如果语句执行完成了,事务提交,这时候数据库系统就认为又到了一个一致性状态,而如果出现问题,系统则将操作回滚,返回初始状态,因为这也是一个一致性状态。而如果出现故障重启等事件时,数据库管理系统在重启后就会分析日志,将所有begin/end全都有的事务跳过或重做,而只有begin没有end的事务则undo,从而保证数据库在可用的时候都是一致性状态。

三, 数据库并发事务存在的问题(脏读、不可重复读、幻读等)

一个数据库可能拥有多个访问客户端,这些客户端并发访问数据库时,若没有采取必要的隔离措施,存在以下问题,这些问题分为5类,包括:

三类数据读问题:脏读、不可重复读、幻读;

两类数据更新问题:第一类丢失更新、第二类丢失更新。

1, 脏读:一个事务读取到了另一个事务中尚未提交的数据;

1.1, (针对未提交数据)如果一个事务中对数据进行了更新,但事务还没有提交,另一个事务可以“看到”该事务没有提交的更新结果,这样造成的问题就是,如果第一个事务回滚,那么,第二个事务在此之前所“看到”的数据就是一笔脏数据。

2, 不可重复读: 一个事务中两次读取的数据内容不一致,要求的是一个事务中多次读取时,数据是一致的,这是事务 update 时引发的问题;

2.1, (针对其他提交前后,读取数据本身的对比)不可重复读取是指同一个事务在整个事务过程中对同一笔数据进行读取,每次读取结果都不同。如果事务1在事务2的更新操作之前读取一次数据,在事务2的更新操作之后再读取同一笔数据一次,两次结果是不同的,所以,Read Uncommitted也无法避免不可重复读取的问题。

3, 幻读: 一个事务中两次读取的数据的数量不一致,要求在一个事务多次中,多次读取时,事务的数量是一致的,这是 insert 或 delete 时引发的问题。

3.1, (针对其他提交前后,读取数据条数的对比) 幻读是指同样一笔查询在整个事务过程中多次执行后,查询所得的结果集是不一样的。幻读针对的是多笔记录。在Read Uncommitted隔离级别下, 不管事务2的插入操作是否提交,事务1在插入操作之前和之后执行相同的查询,取得的结果集是不同的,所以,Read Uncommitted同样无法避免幻读的问题。

3.2, 不可重复读和幻读的区别是:前者是指读到了已经提交的事务的更改数据(修改或删除),后者是指读到了其他已经提交事务的新增数据。对于这两种问题解决采用不同的办法:

3.2.1, 防止读到更改数据,只需对操作的数据添加行级锁,防止操作中的数据发生变化;

3.2.2, 防止读到新增数据,往往需要添加表级锁,将整张表锁定,防止新增数据(oracle采用多版本数据的方式实现)。

4, 第一类丢失更新:A事务撤销时,把已经提交的B事务的更新数据覆盖了

例如:这时候取款事务A撤销事务,余额恢复为1000,这就丢失了更新。

这里写图片描述

 

5, 第二类丢失更新:A事务提交时,覆盖B事务已经提交的数据,造成B事务所做的操作丢失


这里写图片描述

 

四, 数据库的事务隔离级别

1, 概述:

为了解决上述问题,数据库通过锁机制解决并发访问的问题。

根据锁定对象不同:分为行级锁和表级锁;

根据并发事务锁定的关系上看:分为共享锁定和独占锁定,共享锁定会防止独占锁定,但允许其他的共享锁定。而独占锁定既防止共享锁定也防止其他独占锁定。

为了更改数据,数据库必须在进行更改的行上施加行独占锁定,insert、update、delete 和 select for update 语句都会隐式采用必要的行锁定。

但是直接使用锁机制管理是很复杂的,基于锁机制,数据库给用户提供了不同的事务隔离级别,只要设置了事务隔离级别,数据库就会分析事务中的sql语句然后自动选择合适的锁。


2,  不同的隔离级别对并发问题的解决情况如图:

注意:事务的隔离级别和数据库并发性是成反比的,隔离级别越高,并发性越低。
这里写图片描述

2.1, 读未提交:read uncommitted

事务 A 和事务 B ,事务 A 未提交的数据,事务 B 可以读取到;

这里读取到的数据叫做 “脏数据” ;

这种隔离级别最低,一般在理论上存在,数据库隔离级别一般都高于该级别;

2.2, 读已提交:read committed

事务 A 和事务 B ,事务A提交的数据,事务B才能读取到;

此种隔离级别高于读未提交;

这种隔离级别可以避免“脏数据”,但是会导致“不可重复读取”;

Oracle默认隔离级别;

2.3, 可重复读: repeatable read

事务A和事务B,事务A提交之后的数据,事务B读取不到;

这种隔离级别高于读已提交;

可以避免“不可重复读取”,达到可重复读取,但是会导致“幻像读”;

MySQL默认级别

 

2.4, 串行化: serializable

事务A和事务B,事务A在操作数据库时,事务B只能排队等待;

这种隔离级别很少使用,吞吐量太低,用户体验差;

可以避免“幻读”, 每一次读取的都是数据库中真实存在的数据, 事务A与事务B串行,而不并发。


 

 

 

 

 

 

 

 

参考链接:https://blog.csdn.net/starlh35/article/details/76445267

 

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值