小程序开发设计在提升企业数字化转型效率中的关键作用
906
2022-11-19
Spring声明式数据库事务的使用-隔离级别
上面我们只是简单的使用事务,这里将讨论Spring事务机制中最重要的两个配置项,即隔离级别与传播行为。毫无疑问本节内容是本章的核心内容,也是互联网企业最关注的内容之一,因此他十分重要,值得花费大的篇幅去讨论。我们从这两个配置项的大概含义谈起 首先是隔离级别,因为互联网时刻存在着高并发的环境,如商品库存,时刻都是多个线程共享的数据,这样就会在多线程的环境中扣减商品库存。对于数据库而言,时刻都是多个事务同时访问同一记录的情况,这样引起数据出现不一致的情况,便是数据库的丢失更新问题(Lose update)问题。应该说,隔离级别是数据库的概念,有些难度,所以在使用它之前应该先了解数据库的相关知识
1. 数据库事务的知识
数据库事务具有一下四个特征:
- Atomic(原子性):事务中包含的操作被看作一个整体的单元,这个业务单元中的操作要么完全成功,要么完全失败。不会出现部分成功,部分失败的场景
- Consistency(一致性):事务在完成时,必须使所有的数据都保持一致的状态,在数据库中所有的修改都基于事务,保证了数据的完整性。
- Isolation(隔离性):一个事务中的操作语句所作的修改必须与其他事务所作的修改相互隔离。在进行事务查看书就时数据所处的状态,要么是被另一个并发事务修改之前的状态,要么是被另一个事务修改之后的状态,即当前事务不会查询由另一个并发事务正在修改的数据。这种特性通过锁机制实现。这是我们讨论的核心内容。正如上述,可能多个应用程序线程同时访问同一个数据,这样数据库同样的数据就会在各个不同的事务中被访问,这样就会产生丢失更新。为了压制丢失更新的产生,数据库定义了隔离级别的概念,通过他的选择,可以在不同程度上压制丢失更新的产生。因为互联网的应用常常面临高并发的场景,所以隔离性是需要掌握的重点内容
- Durability(持久性):事务结束后所有的数据都会固化到一个地方,如保存在磁盘中,即断电重启之后也可以提供给应用程序使用。
这四个特性除了隔离性都还是比较好理解的,所以这里才会更加深入的讨论隔离性。再多个事务同时操作数据的情况下,会引发丢失更新的场景。例如,电商有一种商品,在疯狂抢购中,会出现多个事务同时访问商品库存的场景,这样就会产生丢失更新。易班而言,存在两种类型的丢失更新。让我们了解他们。下面假设一种商品库存数量还有100,每次抢购都只能抢购1件商品,那么在抢购中就可能出现如下这种场景。
可以看到,T5时刻事务1回滚,导致原本库存99的变成了100,显然事务2的结果就丢失了,这就是一个错误的值。对于这样一个事务回滚另一个事务提交而引发的数据不一致的情况,我们称之为第一类丢失更新。
撤销一个事务的时候,会把其他事务已经提交的更新数据覆盖掉。这是完全没有事务隔离级别造成的。如果事务2被提交,事务1被撤销,那么连同事务2的更新也会被撤销
然而他却已经没有讨论价值了,因为目前大部分的数据库已经克服了第一类丢失更新的问题,也就是现在数据库系统不会出现上表的情况了,所以对于这样的场景不再深入讨论,而是讨论第二类丢失更新,也就是多个事务都提交的场景。
如图,如果多个事务并发提交会出现怎样的场景呢?
注意T5时刻提交的事务。因为在事务1中,无法感知事务2的操作,这样他就不知道事务2已经修改过数据,因为他依旧人为只是发生了一笔业务,所以库存变成了99,而这个结果又是一个错误的结果。这是T5时刻事务1提交的事务,就会引发事务2提交结果的丢失,我们把这样的多个事务都提交引发的丢失gentian称之为第二类丢失更新。这就是我们互联网系统重点关注的内容。为了克服这些问题,数据库提出了事务之间的隔离级别的概念,这就是本章的重点内容之一。
2.详解隔离级别
上面我们讨论了第二类丢失更新。为了压制丢失更新,数据库标准提出了4类隔离级别,在不同程度上压制丢失更新,这四类隔离级别是未提交读,读写提交,可重复读和串行化,他们会在不同程度上压制丢失更新的情景。
//使用隔离级别
(isolation = Isolation.SERIALIZABLE, timeout = 1) public int save(SysRole record) { return sysRoleMapper.insert(record);`在这里插入代码片` }
上述代码我们使用序列化的隔离级别来保证数据的一致性,这使得他将阻塞其他的事务进行并发,所以他只能运行在那些低并发而又需要保证数据一致性的场景下。对于高并下又要保证数据一致性的场景,则需要另外处理了。 当然有时候一个个的指定隔离级别会很不方便,因此Spring Boot可以通过配置文件指定默认的隔离级别。例如,当我们需要把隔离级别设置为读写提交时,可以在application.yml文件中加入默认的配置,如下代码
#隔离级别数字配置的定义#-1数据库默认隔离级别(MySQL重复读)#1 未提交读#2 读写提交#4 可重复读#8 串行化#druid数据库连接池默认隔离级别spring: datasource: #数据源 type: com.alibaba.druid.pool.DruidDataSource druid: #druid数据源默认隔离级别 default-transaction-isolation: 2 tomcat: #tomcat数据源默认隔离级别
代码中配置了tomcat数据源的默认隔离级别,以及druid数据源的隔离级别,注释中已经说明了数字代表的隔离级别,相信读者也会有一个比较清晰的认识,这里配置2说明数据库的隔离级别默认为读写提交
[com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@19c466cb]
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~