大家好。你好。
在大多数涉及数据库操作的项目中,事务控制和事务处理是一个不可避免的问题。例如,当需要控制和处理SQL执行过程时,总体处理流程如下:
。
首先,启动事务,然后执行特定的SQL,如果执行异常,则回滚事务,否则提交事务,最后关闭事务以完成整个过程。按照此过程的逻辑,编写相应的实现代码:
如您所见,上述代码块的逻辑并不复杂;这只是出于业务目的的插入操作。然而,混合事务控制代码明显干扰了对业务自身代码处理逻辑的读取和理解。
在常规项目的代码中,有许多场景涉及数据库处理,如果每个地方都有这样的事务控制逻辑,那么整个代码的可维护性就会很差,这让人难以想象。
幸运的是,许多JAVA项目现在都是基于Spring框架构建的。由于框架的封装,还可以轻松地在业务代码中执行事务控制操作,可以直接添加注释,大大简化了对业务代码的入侵。您对事务注释有透彻的理解吗 您知道注释可能无法按预期方式工作的任何情况吗 您知道如何使用它来最小化对性能的影响吗
让我们来探讨这些问题。
Spring数据库事务约定处理逻辑流程如下图所示,与前面示例中的事务处理相比,Spring事务处理操作移交给Spring框架。开发人员只需要实现自己的业务逻辑,这大大简化了事务处理输入。
。
基于Spring事务机制,实现上述DB操作事务控制的代码,我们的代码将变得非常简洁:
与JDBC事务实现代码相比,基于Spring的方法只需要添加注释,并且只需要在代码中实现业务逻辑,这使得事务控制机制对业务代码的干扰更小。
参数指定当前事务是否为只读事务。设置为true表示事务是只读的。默认值为false。
这里涉及一个称为只读事务的概念,其描述如下:
多个查询语句一起执行的场景中涉及的概念。从事务设置到事务结束,其他事务提交的写操作数据对事务不可见。
下面是一个例子:
现在,您有了一个由两个SQL查询组成的复合查询操作:获取用户表计数,然后获取用户表中的所有数据。
我们首先得到用户表计数,然后得到10
在执行后一条语句之前,另一个进程操纵数据库并将一段新数据插入用户表
执行复合操作的第二条SQL语句,即获取用户列表的操作,并返回11条记录
很明显,复合操作中的两条SQL语句获取不匹配的数据结果。这个问题是由非原子操作引起的,即在两个查询操作之间,另一个写操作修改了目标读取的数据,从而导致了这个问题。
。
为了避免这种情况,可以将只读事务添加到复合查询操作中,以便在事务控制范围内看不到事务之外的写操作。这样,可以确保事务中多个查询语句的执行结果的一致性。
那么,为什么要将其设置为只读事务而不是常规事务呢 主要从效率的角度来看。由于这些操作是只读的,因此它们被设置为只读事务。数据库为只读事务提供了一些优化,例如不启动回滚段、不记录回滚日志等。
可以传入四个不同的属性来设置回滚条件:
意思是
用于指定一个或多个需要回滚的特定异常类型。指定或更高版本时,只有在方法执行逻辑中抛出指定的异常类型时才会触发事务回滚
与中一样,设置类名的字符串格式
用于指定不需要回滚的异常类型。当在方法中引发指定类型的异常时,不会回滚任何事务。其余类型的异常将触发事务回滚。
与中一样,设置类名的字符串格式
类似地,和的使用与上面所示的类似,只是功能点的含义相反。
用于指定此事务的传播类型。所谓的事务传播类型是指当前在事务上下文中需要启动事务时将打开的新事务的处理策略。
有七种主要的事务传播类型:
传输类型
描述
如果存在事务,它将加入该事务。如果没有当前事务,请创建一个新事务
如果存在事务,它将加入该事务。如果没有当前事务,它将继续以非事务方式运行
如果存在事务,它将加入该事务。如果没有当前事务,则引发异常
创建新事务并挂起当前事务如果存在
以非事务方式运行,如果存在当前事务,则挂起该事务
从未
以非事务方式运行,如果事务当前存在,则引发异常
嵌套
事务的传播行为将影响事务控制的结果。例如,如果在同一事务中遇到异常,所有操作都将回滚。如果它在多个事务中,则一个事务的回滚不会影响其他已提交事务的回滚。
属性可用于设置事务将超时的秒数。默认值为-1,这意味着它永远不会超时。
Spring的事务实现原则是AOP,AOP的原则是动态代理。
。
当类内方法相互调用时,它们本质上是对类对象本身的调用,而不是使用代理对象,并且AOP不会触发,Spring无法将事务控制的逻辑编织到调用代码流中,因此事务控制不会生效。
因此,当同一类中的多个方法相互调用并且被调用的方法需要由事务控制时,我们需要特别注意这个问题。解决方案是创建两个不同的类,并在这两个类中放置方法,这样就可以进行跨类调用,并且Spring的事务机制可以生效。
这很容易理解。业务代码将捕获所有异常并将其消化。这相当于业务代码认为捕获的异常不需要触发回滚。就框架而言,不会触发异常回滚机制,因为捕获了异常并且业务逻辑执行正常进行。
因为事务处理会对性能产生影响,所以不能在任何地方添加事务。在某些性能敏感的场景中,请注意以下几点:
仅在必要时添加事务控件
无数据库操作相关,无需添加事务控制
单查询语句,无需添加事务控制
在查询操作只执行多个SQL执行操作的场景中,可以添加只读事务控制
单语句,实际上不需要添加事务处理,因为单语句执行实际上数据库中有一个隐藏的事务控制机制,如果执行失败,就是一个错误,数据将无法成功更新,自然不需要回滚。
最小化事务控制的代码段范围
主要从性能级别、事务机制来看,类似于并发场景中的锁定过程,范围越大,对性能的影响越明显
在事务控制范围内保持业务逻辑尽可能简单,避免与事务无关的耗时处理逻辑
为了提高性能,耗时的逻辑应该在事务的控制之外执行,并且只有与DB操作相关的逻辑应该保留在事务中
我很精明,谈论技术,而不仅仅是谈论技术~
我期待着与你讨论,一起成长为一个更好的自己。
。
我们首先得到用户表计数,然后得到10
发表评论