数据库事务与事务隔离级别说明

1 什么事务

事务是由N步数据库操作序列组成的逻辑执行单元,这系列操作要么全部执行,要么全部放弃执行

2 事务的特性
  • 原子性(Atomically):事务是应用中不可再分的最小执行体
  • 一致性(Consistency):执行的结果需使得数据从一个一致性状态变为另一个一致性的状态
  • 隔离性(Isolation):各个事务的执行互不干扰,任何事物的内部操作对其他事务都是隔离的
  • 持久性(Durability):事务一旦提交,对数据所作的任何改变都要记录到永久存储器中【数据库】
3事务的隔离性与隔离级别

在高并发的场景下,每个线程将使用不同的事务对数据库中的数据进行处理,在各个事务互不影响的情形下,容易发生下列并发异常:【强调cpu的执行速度极快,考虑到网络延时等问题,异常会在极短的时间内发生】

  • 第一类丢失更新,第二类丢失更新
  • 脏读,幻读,不可重复读

第一类丢失更新:某一个事务的回滚导致另一个事务更新的数据丢失

在这里插入图片描述

第二类丢失更新:某一个事务的提交导致另一个事务更新的数据丢失

在这里插入图片描述

脏读:某个事务读取到另一个事务还未提交的数据

在这里插入图片描述

不可重复读:某一个事务前后读取的数据结果不一致【强调的数据的修改】

在这里插入图片描述

幻读 :某一个事务对表查询的行数不一致【强调数据的插入,删除】

在这里插入图片描述

为了解决以上事务隔离性带来的问题,事务存在相应的隔离级别,隔离级别从低到高

隔离级别含义
1 Read Uncommitted(未提交读)一个事务能读取到其他事务修改过,但是还没有提交的(Uncommitted)的数据。上述异常均会发生
2Read Committed(已提交读)一个事务能读取到其他事务提交过(Committed)的数据。一个事务在处理过程中如果重复读取某一个数据,而且这个数据恰好被其他事务修改并提交了,那么当前重复读取数据的事务就会出现同一个数据前后不同的情况。会发生“不可重复读,幻读”的异常
3Repeatable read(可重复读)一个事务一旦开始,事务过程中所读取的所有数据不允许被其他事务修改。它只“保护”了它读取的数据不被修改,但是其他数据会被修改。如果其他数据被修改后恰好满足了当前事务的过滤条件(where语句),那么就会发生“幻影读”的情况。
4Serializable(序列化)系统中所有的事务以串行地方式逐个执行,所以能避免所有数据不一致情况。但是这种以排他方式【加锁】来控制并发事务,串行化执行方式会导致事务排队,系统的并发量大幅下降

在这里插入图片描述

4事务实现机制
4.1数据库锁(悲观锁)

通过给数据库中被操作的数据加锁来实现,分为共享锁【读锁】,互斥锁【写锁】

给数据库加锁防止数据冲突的方式通常称作悲观锁,顾名思义,悲观锁是基于一种悲观的态度类来防止一切数据冲突,它是以一种预防的姿态在修改数据之前把数据锁住,然后再对数据进行读写,在它释放锁之前任何人都不能对其数据进行操作,直到前面一个人把锁释放后下一个人数据加锁才可对数据进行加锁,然后才可以对数据进行操作,特点:可以完全保证数据的独占性和正确性,因为每次请求都会先对数据进行加锁, 然后进行数据操作,最后再解锁,而加锁释放锁的过程会造成消耗,所以性能不高;
1 在事务 A 对数据加了读锁后,其他的事务只能对同样的数据加读锁,进行读操作,不能加写锁,修改数据 \textcolor{red}{1在事务A对数据加了读锁后,其他的事务只能对同样的数据加读锁,进行读操作,不能加写锁,修改数据} 1在事务A对数据加了读锁后,其他的事务只能对同样的数据加读锁,进行读操作,不能加写锁,修改数据
2 在事务 A 对数据加了写锁后,其他的事务对同样的数据既不能加读锁也不能加写锁,禁止对数据的读写操作 \textcolor{Blue}{2在事务A对数据加了写锁后,其他的事务对同样的数据既不能加读锁也不能加写锁,禁止对数据的读写操作} 2在事务A对数据加了写锁后,其他的事务对同样的数据既不能加读锁也不能加写锁,禁止对数据的读写操作

4.2 乐观锁

乐观锁是对于数据冲突保持一种乐观态度,操作数据时不会对操作的数据进行加锁(这使得多个任务可以并行的对数据进行操作),只有到数据提交的时候才通过一种机制来验证数据是否存在冲突(一般实现方式是通过加版本号然后进行版本号的对比方式实现);
乐观锁是一种并发类型的锁,其本身不对数据进行加锁通而是通过业务实现锁的功能,不对数据进行加锁就意味着允许多个请求同时访问数据,同时也省掉了对数据加锁和解锁的过程,这种方式因为节省了悲观锁加锁的操作,所以可以一定程度的的提高操作的性能,不过在并发非常高的情况下,会导致大量的请求冲突,冲突导致大部分操作无功而返而浪费资源,所以在高并发的场景下,乐观锁的性能却反而不如悲观锁。
版本号的实现机制通常是在需要卡控数据的表中加一列信息 (version),用来存储数据当前的版本信息。

在这里插入图片描述
当多个事务同时需要修改Name字段时,先要获取当前数据的版本号,修改字段时 需要执行:
update A set Name=lisi,version=version+1 where ID=#{id} and version=#{version} ,此时需要check version是否与初始获取的版本号一致。

如果存在A事务成功修改数据后,版本号加一,那么后来的事务会因为版本号不一致的原因修改数据失败。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值