声明式事务及编程式事务

目录

1.事务说明

2.事务及数据库的隔离级别

3.事务的传播行为

4.声明是事务

5.编程式事务

6.避免长事务的方式


1.事务说明

数据库的事务是一组操作的集合,这些操作要么全部成功,要么全部失败。用于确保事务的一致性及完整性,事务的主要特性可以通过ACID原则来概括

  1. 原子性 (Atomicity)

    事务中的所有操作要么全部完成,要么全部不完成。如果事务中任一操作失败,整个事务都会被回滚,保持数据在执行前的状态。
  2. 一致性 (Consistency)

    事务必须使数据库从一个一致性状态转换到另一个一致性状态。在事务开始之前和结束之后,数据库的完整性约束必须得到满足。
  3. 隔离性 (Isolation)

    并发执行的事务之间应相互独立,一个事务的执行不应影响其他事务的执行。不同的隔离级别会影响事务的并发行为,如未提交读、已提交读、可重复读和串行化等。
  4. 持久性 (Durability)

    一旦事务提交,其结果是永久性的,即使系统发生崩溃,提交的数据也不会丢失。数据库管理系统通常通过日志或其他持久存储机制来实现这一点。

2.事务及数据库的隔离级别

    Read Uncommitted(读未提交)

  • 描述:在这个级别下,一个事务可以读取另一个事务未提交的数据。这意味着事务可以看到其他事务对数据所做的更改,即使这些更改尚未被提交。
  • 优点:性能最高,因为不需要锁定数据。
  • 缺点:可能导致脏读、不可重复读和幻读。

    Read Committed(读已提交)

  • 描述:只有已经提交的事务所做的更改才能被读取。在此级别下,事务在读取数据之前会等待其他事务提交。
  • 优点:避免了脏读问题,但仍可能导致不可重复读和幻读。
  • 缺点:虽然性能比Read Uncommitted略低,但总体上仍然比较高效。

    Repeatable Read(可重复读)

  • 描述:在一个事务中,如果读取某个数据行,那么在该事务结束之前,不管其他事务如何更改该数据行,该行的值将始终保持不变。即使其他事务已经提交了更改,当前事务也看不到这些变化。
  • 优点:防止了脏读和不可重复读,但仍可能发生幻读情况。
  • 缺点:增加了性能开销,尤其是在高并发场景下。

    Serializable(可串行化)

  • 描述:这是最严格的隔离级别,在这个级别下,事务完全隔离。事务的执行就好像所有事务是串行执行的一样,不会有任何干扰。
  • 优点:绝对的一致性,防止所有并发问题,包括脏读、不可重复读和幻读。
  • 缺点:性能最低,因为它可能会导致大量的锁竞争和阻塞。

在Spring中,你可以通过@Transactional注解来设置事务的隔离级别。例如:

import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

@Transactional(isolation = Isolation.REPEATABLE_READ)
public void myTransactionalMethod() {
    // 业务逻辑
}

脏读:指的是一个事务读取了另一个尚未提交的事务所修改的数据。这种情况可能导致读取到的数据不可靠,因为被读取的数据可能会在后续被回滚,从而使得第一个事务得到的信息变得无效。

不可重复读:它指的是在同一事务中,对同一数据的两次读取可能得到不同的结果。这种情况通常发生在以下场景中:

  1. 事务A读取了某个数据项(例如,价格)。
  2. 事务B在事务A的读取后对该数据项进行了修改。
  3. 事务A再次读取同一数据项时,可能会发现数据已被事务B修改过,从而得到不同的结果。

 幻读:指在同一事务中,反复执行相同的查询操作时,结果集会出现不同的数据情况。具体来说,当一个事务在读取数据后,另一个事务对数据库进行了插入或删除操作,导致第一个事务再次执行相同查询时,能够看到新插入的行(或缺失被删除的行),这就称为幻读

3.事务的传播行为

        描述了当一个事务调用另一个事务时,如何处理事务边界和事务上下文。常见的传播行为包括:

  • REQUIRED:如果存在当前事务,则加入该事务;如果没有,则创建新事务。
  • REQUIRES_NEW:总是创建一个新的事务,如果存在当前事务则挂起它。
  • NESTED:支持嵌套事务,允许在当前事务中开启一个子事务。
  • MANDATORY:要求当前操作必须在一个已有的事务中进行。如果存在当前事务,则加入该事务;如果没有,则抛出异常
  • SUPPORTS:如果有当前事务则参与,否则以非事务方式执行。
  • NOT_SUPPORTED:不支持事务,如果存在事务则挂起。
  • NEVER:不支持事务,若存在事务则抛出异常。

4.声明是事务

声明式事务通过Transactional注解进行实现,是基于AOP的,本质是在方法执行前后进行拦截,在方法执行前开启事务,在方法之后后按照不同的情况进行事务的提交和回滚。

Transactional注解的参数说明

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Transactional {
//当配置了多个事务管理器时,指定选择哪一个事务管理器
    @AliasFor("transactionManager")
    String value() default "";
//和上个参数一致
    @AliasFor("value")
    String transactionManager() default "";

    String[] label() default {};
//设置事务的传播行为
    Propagation propagation() default Propagation.REQUIRED;
//设置事务的隔离级别
    Isolation isolation() default Isolation.DEFAULT;
//事务的超时时间
    int timeout() default -1;
//和上面一样
    String timeoutString() default "";
//指定事务是否为只读事务,为了忽略那些不需要事务的方法,比如读取数据
    boolean readOnly() default false;
//执行触发回滚的异常类型
    Class<? extends Throwable>[] rollbackFor() default {};
//和上面一样
    String[] rollbackForClassName() default {};
//抛出指定的异常,不会滚事务
    Class<? extends Throwable>[] noRollbackFor() default {};
//和上面一样
    String[] noRollbackForClassName() default {};
}

优点:

不需要通过编程的方法管理事务,即不要进行事务手动开启,提交及回滚,直接在需要添加事务的方法上使用@Transactional注解即可

缺点:

最细粒度只能是方法级别,无法像编程事务可以作用到代码块级别

事务失效的几种情况:

  • 使用在非public方法上会导致事务失效
  • 同一个类中,一个无事务的方法内通过this方式调用有事务的方法会导致事务失效
  • 异常被捕捉了导致事务失效

5.编程式事务

编程式事务允许开发者在代码中明确地控制事务的开始、提交和回滚。使用Spring的事务管理器,你可以通过TransactionTemplate或直接使用PlatformTransactionManager来实现编程式事务管理。

PlatformTransactionManager示例:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;   


 @Override
    public int insertConfig() {
        DefaultTransactionDefinition def = new DefaultTransactionDefinition();
        // 设置事务的传播机制
        def.setPropagationBehavior(DefaultTransactionDefinition.PROPAGATION_REQUIRED);
        // 设置事务的隔离级别
        def.setIsolationLevel(DefaultTransactionDefinition.ISOLATION_REPEATABLE_READ);
        // 开始事务
        TransactionStatus status = transactionManager.getTransaction(def);
        try {
            SysConfig config;
            for (int i = 0; i < 5; i++) {
                config = new SysConfig();
                config.setConfigName("配置" + i);
                configMapper.insertConfig(config);
                if (i == 2) {
                    throw new RuntimeException();
                }
            }
            // 提交事务
            transactionManager.commit(status);
        } catch (Exception e) {
            // 回滚事务
            transactionManager.rollback(status);
            throw e;
        }
        return 1;
    }

TransactionTemplate示例:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;  

  public int insertConfig2() {
        transactionTemplate.execute(status -> {
            try {
                SysConfig config;
                for (int i = 0; i < 5; i++) {
                    config = new SysConfig();
                    config.setConfigName("配置" + i);
                    configMapper.insertConfig(config);
                    if (i == 2) {
                        throw new RuntimeException();
                    }
                }
            } catch (Exception e) {
                status.setRollbackOnly();
                throw e;
            }
            return 1;
        });
        return 1;
    }

通过编程式事务可以手动控制事务的范围 

6.避免长事务的方式

①不要在整个大方法上添加Transactional注解,将增删改操作放在一个独立的方法,在这个方法上使用Transactional注解,注意注解失效的情况。

②使用编程式事务,在需要的代码中进行事务控制

③事务中避免远程调用,通过建立重试补偿机制,保证数据的一致性

④事务中避免一次处理太多的数据,可以进行分批处理,处理成功直接提交。这种情况出现异常无法对所有的数据进行回滚,需要将异常的数据返回至前端,或者通过钉钉的方式进行提醒,让用户对异常的数据进行二次处理。例如一次导入大批量数据的情况

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/871266.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

PHP导出生成PDF文件开源组件:mPDF使用详情

最近在使用php要实现一个把旅游线路导出成pdf文件下载&#xff0c;在全网搜索了一遍有几个常用的开源组件&#xff0c;在PHP中生成PDF文件&#xff0c;比如FPDF、TCPDF、mPDF等。在对比了一圈后就 mPDF开源地址&#xff1a; https://github.com/mpdf/mpdf mPDF版本说明 PHP…

探索地理空间分析的新世界:Geopandas的魔力

文章目录 探索地理空间分析的新世界&#xff1a;Geopandas的魔力背景&#xff1a;为何选择Geopandas&#xff1f;这个库是什么&#xff1f;如何安装这个库&#xff1f;五个简单的库函数使用方法场景应用&#xff1a;Geopandas在实际工作中的应用常见bug及解决方案总结 探索地理…

鲲鹏服务器安装Kafka

由于项目需求&#xff0c;需要在鲲鹏云主机上安装Kafka&#xff0c;并且要求安装的版本为2.3.X。下面主要从以下几个步骤说明如何安装&#xff1a; 1、下载kafka的安装文件 2、上传到服务器 3、修改配置 4、启动 5、使用工具测试 服务器信息 CPU信息 [rootecs02 ~]# lscpu A…

集团数字化转型方案(六)

集团数字化转型方案旨在通过引入前沿技术&#xff0c;如人工智能&#xff08;AI&#xff09;、大数据分析、云计算和物联网&#xff08;IoT&#xff09;&#xff0c;全面提升业务运营效率和市场竞争力。该方案首先实现业务流程的自动化&#xff0c;减少人工干预&#xff0c;通过…

第1章-05-通过浏览器控制台安装JQuery.js库

🏆作者简介,黑夜开发者,CSDN领军人物,全栈领域优质创作者✌,CSDN博客专家,阿里云社区专家博主,2023年CSDN全站百大博主。 🏆数年电商行业从业经验,历任核心研发工程师,项目技术负责人。 🏆本文已收录于专栏:Web爬虫入门与实战精讲。 🎉欢迎 👍点赞✍评论⭐收…

自抗扰控制ADRC原理解析及案例应用

1. ADRC基本原理 1.1 ADRC的基本概念 自抗扰控制&#xff08;Active Disturbance Rejection Control&#xff0c;ADRC&#xff09;是一种先进的控制策略&#xff0c;由韩京清研究员于1998年提出。ADRC的核心思想是将系统内部和外部的不确定性因素视为总扰动&#xff0c;并通过…

网络编程:OSI协议,TCP/IP协议,IP地址,UDP编程

目录 国际网络通信协议标准&#xff1a; 1.OSI协议&#xff1a; 2.TCP/IP协议模型&#xff1a; 应用层 &#xff1a; 传输层&#xff1a; 网络层&#xff1a; IPV4协议 IP地址 IP地址的划分&#xff1a; 公有地址 私有地址 MA…

win/mac数字资产管理软件Adobe Bridge (BR)软件下载安装

目录 一、Adobe BR软件介绍 1.1 软件概述 1.2 主要功能 1.3 系统要求 二、Adobe BR安装步骤 2.1 下载软件 2.2 安装前准备 2.3 安装过程 三、Adobe BR使用教程 3.1 基础操作 3.1.1 浏览与预览 3.1.2 搜索与筛选 3.1.3 批量操作 3.2 进阶功能 3.2.1 元数据管理 …

海康VisionMaster使用学习笔记12-通信框架介绍

1. 通信的用途 用途: 通信是连通算法平台和外部设备的重要渠道&#xff0c;在算法平台中既支持外部数据的读入也支持数据的写出&#xff0c;当通信构建起来以后既可以把软件处理结果发送给外界&#xff0c;又可以通过外界发送字符来触发相机拍照或者软件运行。 2. 通信的种类…

面试题目:(4)给表达式添加运算符

目录 题目 代码 思路解析 例子 题目 题目 给定一个仅包含数字 0-9 的字符串 num 和一个目标值整数 target &#xff0c;在 num 的数字之间添加 二元 运算符&#xff08;不是一元&#xff09;、- 或 * &#xff0c;返回 所有能够得到 target 的表达式。1 < num.length &…

Activity的基本用法

文章目录 Activity的基本用法活动是什么新建活动在AndroidManifest文件中注册Acyivity销毁一个活动 Activity的基本用法 活动是什么 **活动&#xff08;Activity&#xff09;是最容易吸引用户的地方&#xff0c;它是一种可以包含用户界面的组件&#xff0c;主要用于和用户进行…

使用 SQLite 处理大量小数据库

使用 SQLite 处理大量小数据库时&#xff0c;需要考虑数据库文件的数量、管理方式、性能优化等因素。SQLite 是轻量级的数据库&#xff0c;适合嵌入式系统和小型项目&#xff0c;但在处理大量数据库文件时&#xff0c;仍需要仔细设计和管理。 一、问题背景 近期一个项目中&…

2024 人工智能最前沿:分享几个大模型(LLMs)的热门研究方向

引言 在人工智能领域&#xff0c;大模型的研究正迅速发展&#xff0c;当前涵盖了很多个研究方向&#xff0c;每个方向都带有其独特的研究重点和挑战。下面给大家盘点几个比较热门的研究方向&#xff0c;主要包括检索增增强生成RAG、大模型Agent、Mamba、MoE、LoRA等&#xff0…

JavaScript - Ajax

Asynchronous JavaScript And XML&#xff0c;异步的JavaScript和XML 作用: 数据交换&#xff1a;通过Ajax可以给服务器发送请求&#xff0c;并获取服务器响应的数据。异步交互&#xff1a;可以在不重新加载整个页面的情况下&#xff0c;与服务器交换数据并更新部分网页的技术…

从台架到实车的语音识别专项测试分析笔记

(网络资源图) 一.语音识别原理及测试范围 1.语音识别的原理: ①.通过麦克风输入人的声音 ②.声学处理:处理掉杂音,噪音 ③.特征处理:提取声音中的关键因素 如:小米 xiao mi ④.模型匹配: 如xiaomi 可以匹配小米或者小蜜,需要根据前后内容计算出概率最大内容进行输出给用户确认…

Leetcode每日刷题之3.无重复字符的最长子串(C++)

1.题目解析 本题的目标是在给定的字符串中找出不含有重复字符的最长子串&#xff0c;并且返回其长度&#xff0c;这道题核心就是如何去重并且不能遗漏以保证子串长度最长&#xff0c;题目来源:3.无重复字符的最长子串 2.算法原理 本题的算法原理主要是"滑动窗口"也就…

自存实践本地访问 nginx放前端打包好的项目

nginx 部署前端项目_哔哩哔哩_bilibili 将打包好的dits文件放到 配置nginx.conf文件的location 启动命令 start nginx.exe 输入localhost即可访问打包好的项目 关闭nginx .\nginx.exe -s quit

Unity--XLua调用C#

Unity–XLua调用C# 由于Unity/C# 和lua是两种语言&#xff0c;两种语言的特性不一样&#xff0c;因此&#xff0c;如果要互相调用的话&#xff0c;需要第三方作桥梁. 因此&#xff0c;为了在Unity中/C#中使用lua的特性&#xff0c;需要在Unity中安装插件&#xff0c;Xlua/toLu…

IDEA2024中,解决建多级包时不分级显示问题

点击右上角的三个点-----外观----不勾选“压缩空的中间软件包”、“平展软件包”这两项即可。

新加坡vps好不好?新加坡vps深度评测

新加坡vps好不好&#xff1f;新加坡VPS是一个好的选择。其优势在于地理位置优越、网络连接快速以及价格合理&#xff1b;劣势在于带宽资源有限、供应商众多导致选择困难、以及安全性和隐私保护问题。下面小编将针对新加坡vps优劣势进行详细分析&#xff1a; 新加坡VPS的优势&a…