聊一聊数据库事务的那些事(隔离级别,传播行为)

news2024/11/25 12:37:49

 

我们平时使用事务的时候,可能脑子里面想到和事务有关的知识点无非就是,ACID,事务隔离级别那一套,使用的事务也就是是通过注解的形式,或者手动开启事务。更细致一点的问题或许没有深究下去,比如事务的传播行为,注解形式和手动事务的区别等,今天我们就这几个方面进行介绍。

1. 事务的概念

事务是一组数据库操作的执行单元,这些操作要么全部成功执行,要么全部失败回滚。事务具有以下四个基本特性,通常简称为ACID特性:

  • 原子性(Atomicity):事务被视为一个原子操作,要么全部执行成功,要么全部执行失败回滚。如果事务中的任何一步操作失败,那么整个事务会被回滚到事务开始之前的状态,不会留下部分完成的结果。

  • 一致性(Consistency):事务开始之前和事务结束之后,数据库的完整性约束没有被破坏。换句话说,事务的执行将使数据库从一个一致的状态转移到另一个一致的状态。

  • 隔离性(Isolation):并发执行的事务之间应该相互隔离,使每个事务都感觉不到其他事务的存在。事务的隔离性确保了在并发环境中,每个事务都能独立地访问和修改数据,而不会相互干扰或产生不一致的结果。

  • 持久性(Durability):一旦事务提交成功,对数据库的修改将永久保存,即使系统发生故障或重启。持久性确保了事务的结果是可靠和持久的。

2. 事务的隔离级别

为了实现事务的隔离性,数据库定义了不同的隔离级别,用于控制并发事务之间的互相影响程度。常见的隔离级别包括:

  • 读未提交(Read Uncommitted):事务可以读取其他事务尚未提交的数据,可能导致脏读、不可重复读和幻读的问题。

  • 读已提交(Read Committed):事务只能读取已经提交的数据,可以避免脏读,但仍可能导致不可重复读和幻读的问题。

  • 可重复读(Repeatable Read):事务在整个过程中能够多次读取相同的数据,保证了读取的一致性,但仍可能导致幻读的问题。

  • 串行化(Serializable):事务顺序执行,完全隔离了并发事务,保证了最高的隔离性,但可能导致并发性能下降。

3. 事务的传播行为

事务的传播行为是指在多个事务方法相互调用的情况下,如何处理事务的传播和边界。Spring提供了几种不同的传播行为选项,可以根据业务需求进行配置。

以下是几种常用的事务传播行为:

  1. REQUIRED(默认):如果当前存在事务,则加入该事务;如果没有事务,则创建一个新的事务。这是最常用的传播行为。例如:
@Transactional
public void methodA() {
    // 这里会加入调用方的事务,或者创建一个新事务
    methodB();
}

@Transactional
public void methodB() {
    // 该方法也运行在和methodA相同的事务中
}
  1. REQUIRES_NEW:无论当前是否存在事务,都创建一个新的事务。如果存在外部事务,外部事务将被挂起。例如:
@Transactional
public void methodA() {
    // 这里会挂起外部事务,创建一个新事务
    methodB();
}

@Transactional(propagation = Propagation.REQUIRES_NEW)
public void methodB() {
    // 该方法运行在一个新的事务中
}
  1. SUPPORTS:如果当前存在事务,则加入该事务;如果没有事务,则以非事务方式执行。适用于不要求强制事务的场景。例如:
@Transactional
public void methodA() {
    // 这里会加入调用方的事务
    methodB();
}

@Transactional(propagation = Propagation.SUPPORTS)
public void methodB() {
    // 该方法会根据调用方是否有事务来决定是否加入事务
}
  1. NOT_SUPPORTED:以非事务方式执行方法,如果存在当前事务,将会挂起当前事务。适用于不需要事务支持的场景。例如:
@Transactional
public void methodA() {
    // 这里会挂起调用方的事务
    methodB();
}

@Transactional(propagation = Propagation.NOT_SUPPORTED)
public void methodB() {
    // 该方法以非事务方式执行
}
  1. MANDATORY:要求当前存在事务,否则抛出异常。例如:
@Transactional
public void methodA() {
    // 这里会运行在调用方的事务中
    methodB();
}

@Transactional(propagation = Propagation.MANDATORY)
public void methodB() {
    // 该方法要求调用方必须有事务,否则抛出异常
}

这些是一些常见的事务传播行为选项,还有其他一些选项可供选择,如NESTED(如果当前存在事务,则在当前事务的嵌套事务中执行)等。你可以根据具体的业务需求选择适当的传播行为来控制事务的边界和行为。

4. 不同数据库的默认事务隔离级别

不同的数据库管理系统(DBMS)可能具有不同的默认事务隔离级别,并且修改默认事务隔离级别的方法也因DBMS而异。以下是一些常见的数据库和它们的默认事务隔离级别以及如何修改默认事务隔离级别的示例:

  1. MySQL:

    • 默认事务隔离级别:可重复读(REPEATABLE READ)
    • 修改默认事务隔离级别:可以在会话级别或全局级别修改默认事务隔离级别。
      • 会话级别:SET SESSION TRANSACTION ISOLATION LEVEL <isolation_level>;
      • 全局级别:SET GLOBAL TRANSACTION ISOLATION LEVEL <isolation_level>;
  2. Oracle:

    • 默认事务隔离级别:读已提交(READ COMMITTED)
    • 修改默认事务隔离级别:Oracle不支持直接修改默认事务隔离级别。您可以通过在会话级别使用SET TRANSACTION ISOLATION LEVEL <isolation_level>;来设置特定会话的隔离级别。
  3. Microsoft SQL Server:

    • 默认事务隔离级别:读已提交(READ COMMITTED)
    • 修改默认事务隔离级别:可以在数据库级别或会话级别修改默认事务隔离级别。
      • 数据库级别:ALTER DATABASE <database_name> SET READ_COMMITTED_SNAPSHOT ON;
      • 会话级别:SET TRANSACTION ISOLATION LEVEL <isolation_level>;
  4. PostgreSQL:

    • 默认事务隔离级别:读已提交(READ COMMITTED)
    • 修改默认事务隔离级别:可以在会话级别修改默认事务隔离级别。
      • 会话级别:SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL <isolation_level>;

请注意,上述示例中的<isolation_level>是事务隔离级别的具体名称,例如可重复读(REPEATABLE READ)、读已提交(READ COMMITTED)等。这些隔离级别名称可能会因不同的DBMS而略有不同。

在实际使用时,请根据所使用的数据库管理系统的文档和指南来了解默认事务隔离级别以及如何修改它们。这样可以确保您正确地配置事务隔离级别以满足您的应用需求。

5. 注解事务和手动事务

  • 手动管理事务:在手动管理事务的情况下,需要明确地开启、提交和回滚事务。一般步骤包括获取数据库连接、关闭自动提交、执行数据库操作、根据操作结果决定是提交还是回滚事务,并最后关闭数据库连接。这种方式灵活性较高,适用于复杂的事务场景,但需要手动编写事务管理代码。

  • 使用注解管理事务:在使用注解管理事务的情况下,可以使用框架提供的注解来简化事务管理。常见的框架包括Spring Framework和Java Persistence API (JPA)。通过在方法或类上添加相应的注解,可以指定事务的传播行为、隔离级别、回滚条件等。框架会自动管理事务的开启、提交和回滚,减少了手动编写事务管理代码的工作量。

使用注解形式管理事务的示例

@Service
@Transactional
public class UserService {
    
    @Autowired
    private UserRepository userRepository;
    
    public void createUser(User user) {
        userRepository.save(user);
    }
    
    public void updateUser(User user) {
        userRepository.save(user);
    }
    
    public void deleteUser(int userId) {
        userRepository.deleteById(userId);
    }
}

在上述示例中,我们使用了Spring Framework提供的@Transactional注解来管理事务。在UserService类上添加了@Transactional注解,表示该类中的所有方法都将在事务的管理下执行。当调用createUserupdateUserdeleteUser方法时,事务会自动开启、提交或回滚,根据方法的执行结果来决定是否提交或回滚事务。

使用手动事务管理的示例

@Service
public class UserService {
    
    @Autowired
    private UserRepository userRepository;
    
    @Autowired
    private PlatformTransactionManager transactionManager;
    
    public void createUser(User user) {
        TransactionDefinition definition = new DefaultTransactionDefinition();
        TransactionStatus status = transactionManager.getTransaction(definition);
        
        try {
            userRepository.save(user);
            transactionManager.commit(status);
        } catch (Exception e) {
            transactionManager.rollback(status);
            throw e;
        }
    }
    
    public void updateUser(User user) {
        TransactionDefinition definition = new DefaultTransactionDefinition();
        TransactionStatus status = transactionManager.getTransaction(definition);
        
        try {
            userRepository.save(user);
            transactionManager.commit(status);
        } catch (Exception e) {
            transactionManager.rollback(status);
            throw e;
        }
    }
    
    public void deleteUser(int userId) {
        TransactionDefinition definition = new DefaultTransactionDefinition();
        TransactionStatus status = transactionManager.getTransaction(definition);
        
        try {
            userRepository.deleteById(userId);
            transactionManager.commit(status);
        } catch (Exception e) {
            transactionManager.rollback(status);
            throw e;
        }
    }
}

在上述示例中,我们手动管理事务的过程包括以下步骤:

  1. PlatformTransactionManager中获取TransactionDefinition,定义事务的属性。
  2. 通过transactionManager.getTransaction(definition)获取事务的状态。
  3. try块中执行数据库操作,并通过transactionManager.commit(status)提交事务。
  4. 如果在执行过程中捕获到异常,通过transactionManager.rollback(status)回滚事务,并抛出异常。

使用手动事务管理时,需要明确地在适当的地方开启、提交或回滚事务,并处理异常情况,确保事务的正确执行。

6. 事务的应用领域

事务的概念并不仅限于数据库层面,它可以应用于不同的领域和技术栈。虽然最常见的使用场景是在数据库操作中使用事务来确保数据的一致性和完整性,但事务的概念也可以应用于其他场景。

以下是一些示例,展示了事务的应用领域:

  1. 数据库操作:在数据库中,事务用于将一组相关的数据库操作作为一个逻辑单元进行管理。这意味着要么所有操作都成功执行,要么所有操作都被回滚,以保持数据的一致性。

  2. 消息队列:在消息队列系统中,事务可以确保消息的可靠传递。事务可以用来保证消息的发送和接收操作要么同时成功,要么同时失败,从而避免消息丢失或重复消费的问题。

  3. 分布式系统:在分布式系统中,事务可以用于协调多个节点之间的操作,以保证全局的一致性。分布式事务管理器(如2PC、3PC、Saga等)可以用来实现跨多个服务或系统的事务一致性。

  4. 文件系统:在文件系统中,事务可以用来确保文件的完整性。例如,将多个文件的写操作作为一个事务进行管理,要么所有文件都成功写入,要么都不写入,以避免文件损坏或部分写入的问题。

  5. 应用程序开发:在应用程序开发中,事务可以用于确保一系列操作的原子性和一致性。例如,在Java中,可以使用事务管理框架(如Spring Framework)来管理方法的执行,以便在发生异常时回滚事务。

总结来说,事务不仅仅局限于数据库层面,它是一种通用的概念,在各个领域和技术中都有应用。事务的目标是确保一系列操作的一致性,无论是在数据库操作、消息队列、分布式系统、文件系统还是应用程序开发中。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

STM32F407的PWM

文章目录 32的PWM资源PWM输出原理捕获/比较模式寄存器&#xff08;TIMx_CCMR1/2&#xff09;捕获/比较使能寄存器&#xff08;TIMx_CCER&#xff09;捕获/比较寄存器&#xff08;TIMx_CCR1~4&#xff09; 库函数版本的PWM波输出开启 TIM3 时钟以及复用功能时钟置 &#xff0c;配…

对CT数据进行最小最大值归一化(Min-Max Normalization)和消除过暗过亮值处理

文章目录 PIL库的图像失真问题使用最小最大值归一化&#xff08;Min-Max Normalization&#xff09;预处理消除过暗过亮值pytorch中对tensor使用最小最大值归一化处理&#xff08;torchvision.transforms&#xff09; 我们在处理CT图像时&#xff08;以dcm格式为例&#xff09;…

全栈小程序开发路线

目录 个人心得&#xff1a; 我的学习路线 个人心得&#xff1a; 我擅长的是小程序开发和技术变现&#xff0c;从2021年至今开发上线20于个小程序&#xff0c;矩阵用户超过10万&#xff0c;变现10万左右。 以下是部分小程序截图&#xff0c;追风口做的小程序&#xff0c;基本…

「Win」Windows注册表介绍与操作

✨博客主页&#xff1a;何曾参静谧的博客 &#x1f4cc;文章专栏&#xff1a;「Win」Windows程序设计 相关术语 Windows的注册表&#xff1a;是一个重要的系统组件&#xff0c;用于存储操作系统和应用程序的配置信息。它类似于一个数据库&#xff0c;包含了各种键值对、参数、设…

Vue报错:Error: error:0308010C:digital envelope routines::unsupported解决

问题 node 环境 Node.js v18.14.2 使用npm start.出现以下报错 Error: error:0308010C:digital envelope routines::unsupported at new Hash (node:internal/crypto/hash:71:19) at Object.createHash (node:crypto:133:10) at module.exports (F:\RuoYi-Cloud\CourseSched…

SWAT模型系统学习(建模方法、实例应用、高级进阶)

目前&#xff0c;水环境问题逐渐成为制约社会经济和环境可持续发展的重要因素。根据国内外研究表明&#xff0c;受全球环境变化和经济快速发展的影响&#xff0c;面源污染已逐渐成为水环境污染的第一因素。但面源污染由于具有排放分散、隐蔽&#xff0c;排污随机、不确定、不易…

搜索算法(三) 回溯法

1.回溯法 回溯法可以理解成一种特殊的深度优先算法&#xff0c;比起普通的DFS&#xff0c;多了还原当前节点的一步。 修改当前节点、递归子节点、还原当前节点。 本质是一种试错的思想。 维基百科&#xff1a; 2.例题 1&#xff09; 力扣https://leetcode.cn/problems/pe…

树莓派安装系统

0. 实验准备 树莓派一个&#xff0c;TF卡&#xff08;4GB以上&#xff09;一个&#xff0c;读卡器一个 1. 使用官方提供的工具 在搜索引擎中搜索树莓派&#xff08;不要用百度&#xff0c;建议使用必应的国际版进行搜索&#xff09;&#xff0c;我这里直接放上树莓派官方超链…

深入篇【Linux】学习必备:理解【Linux软件包管理器】yum + yum的具体使用 + yum下载的有趣指令

这里写目录标题 Ⅰ.Linux软件包管理器yum①.什么是软件包/什么是yum②.linux的软件生态与yum源③.关于rzsz Ⅱ.yum基本指令①.查看软件②.安装软件③.卸载软件 Ⅲ.yum下载的好玩指令①.sl②.linux_logo③.elinks Ⅰ.Linux软件包管理器yum yum 是一个 Shell 前端软件包管理器。基…

C++ 多态 最详细图文+代码讲解

感谢各位 点赞 收藏 评论 三连支持 本文章收录于专栏【C进阶】 ❀希望能对大家有所帮助❀ 本文章由 风君子吖 原创 回顾 上篇文章&#xff0c;我们学习了继承的相关知识&#xff0c;详细解刨了继承中的各种细节&#xff0c;而本章内容将在继承的基础上学习多态 多态的概念…

Dreamweaver如何进行网页开发?

文章目录 0.引言1.安装Dreamweaver2.编写第一个网页 0.引言 笔者本科学习的编程语言主要是关于桌面开发的&#xff0c;对编程有一定的基础&#xff0c;而编程除了关于桌面软件开发&#xff08;VisualStudio如何进行桌面软件开发&#xff1f;&#xff09;&#xff0c;还有手机应…

网络安全自学笔记+学习路线(超详细)

01 什么是网络安全 网络安全可以基于攻击和防御视角来分类&#xff0c;我们经常听到的 “红队”、“渗透测试” 等就是研究攻击技术&#xff0c;而“蓝队”、“安全运营”、“安全运维”则研究防御技术。 无论网络、Web、移动、桌面、云等哪个领域&#xff0c;都有攻与防两面…

c语言编程练习题:7-193 两小时学完C语言

#include <stdio.h> int main(){int n,k,m;int sum;if (scanf("%d %d %d",&n,&k,&m)!EOF){sum n-k*m;}printf("%d",sum);return 0; }

(学习日记)2023.04.28

写在前面&#xff1a; 由于时间的不足与学习的碎片化&#xff0c;写博客变得有些奢侈。 但是对于记录学习&#xff08;忘了以后能快速复习&#xff09;的渴望一天天变得强烈。 既然如此 不如以天为单位&#xff0c;以时间为顺序&#xff0c;仅仅将博客当做一个知识学习的目录&a…

基于SSM的教务管理系统的设计与实现(论文+源码)_kaic

摘 要 学校教务管理信息化是提高办公效率的主要途径。随着中国高等教育的快速发展和学校规模的不断扩大&#xff0c;在校学生人数不断增加&#xff0c;办学层次出现多元化&#xff0c;由一地办学发展到多地多点办学&#xff0c;同时进一步推行学分制。这些变化使得教务部门的管…

【AI绘图】四、stable difusion提示词如何写?

上一篇&#xff1a;【AI绘图】三、stable diffussion操作界面介绍以及如何使用 如何写好提示词&#xff1f; 写出一份比较好的提示词是文生图技术的关键。但是&#xff0c;写出一份好的prompt并不容易&#xff0c;下面针对“如何写好提示词”这个问题&#xff0c;从提示词构成…

MySQL 数据操纵语言 DML

文章目录 数据操纵语言 DMLINSERT 语句UPDATE 语句DELETE 语句 数据操纵语言 DML 数据操纵语言&#xff08;Data Manipulation Language&#xff0c;DML&#xff09;是 SQL 语言的核心部分之一。在添加、更新或者删除表中的数据时&#xff0c;需要执行 DML 语句。很多时候我们提…

Unity导入Android aar包实现交互全流程

一.搭建Android项目 1.创建一个Android空项目 点击finish后,就等待编译,过程中会自动下载一些插件 等待... 等待... 编译完成: 2.创建Module 右键该工程的app,新建一个Module, Language:Kotlin语法和Java语法,语法不同,后续创建的代码文件有所差异,但不影响代码编…

地震勘探基础(六)之地震反褶积

地震反褶积 地震资料常规处理主要包括地震反褶积&#xff0c;水平叠加和偏移成像三大内容。水平叠加可以提高地震资料的信噪比&#xff0c;偏移成像可以提高地震资料的空间分辨率和保真度&#xff0c;地震反褶积可以提高地震资料的分辨率和压制干扰波。 1954年&#xff0c;Ro…