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

这篇具有很好参考价值的文章主要介绍了聊一聊数据库事务的那些事(隔离级别,传播行为)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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

 

我们平时使用事务的时候,可能脑子里面想到和事务有关的知识点无非就是,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)来管理方法的执行,以便在发生异常时回滚事务。

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

到了这里,关于聊一聊数据库事务的那些事(隔离级别,传播行为)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 数据库事务的四种隔离级别

    事务 数据库事务(简称:事务)是数据库管理系统执行过程中的一个逻辑单元,由一个有限的数据库操作序列构成。——维基百科 简而言之:一系列数据库操作语句组成事务。 数据库事务的隔离级别有四种: 读未提交(Read Uncommitted):事务中的修改可以被其他事务读取,

    2024年02月04日
    浏览(35)
  • 【数据库】事务的隔离级别以及实现原理

    经常提到数据库的事务,那你知道数据库还有事务隔离的说法吗,事务隔离还有隔离级别,那什么是事务隔离,隔离级别又是什么呢?本文就帮大家梳理一下。 事务,由一个有限的数据库操作序列构成,这些操作要么全部执行,要么全部不执行,是一个不可分割的工作单位。

    2023年04月26日
    浏览(31)
  • 【Spring/MySQL数据库系列】数据库事务的特点与隔离级别

    ⭐️ 前面的话 ⭐️ 本文已经收录到《Spring框架全家桶系列》专栏,本文将介绍有关数据库事务的特点以及隔离级别。 📒博客主页:未见花闻的博客主页 🎉欢迎关注🔎点赞👍收藏⭐️留言📝 📌本文由 未见花闻 原创, CSDN 首发! 📆首发时间:🌴2023年5月20日🌴 ✉️坚

    2024年02月05日
    浏览(42)
  • 【后端面经-数据库】MySQL的事务隔离级别简介

    目录 0. 事务的概念 1. 三类问题 2. 事务隔离级别 3. 操作指令 4. 总结 5. 参考博文 事务指的是一连串的集中操作指令,一个事务的执行必须执行完所有的动作才能算作执行结束。事务具有四个特点,简记作 ACID : A -Atomicity: 原子性,事务的执行必须保证所有的动作都执行完毕;

    2024年02月08日
    浏览(36)
  • 【Mysql数据库 第13章】MySQL的事务、事务的隔离级别、事务的保存点

    💖Spring中的创建对象的三种方式、第三方资源配置管理详细描述及使用(XML版完结篇) 💖Spring中的bean的配置、作用范围、生命周期详细描述及使用(XML版上篇) 💖

    2023年04月20日
    浏览(48)
  • elasticsearch的查询方式和mysql数据库事务隔离级别的思考

    目录 普通分页 解除查询限制 scroll查询 search_after 官方改进 轻量级试图(pit,Point in time) 总结 项目中用到了 elasticsearch,发现有几种查询方式不太一样,思考了一下,总结如下 等同于关系数据库的分页查询,例如 mysql 的 limit,如下 sql 这种查询方式有一个问题,需要查询

    2024年01月18日
    浏览(39)
  • 数据库四种事务隔离级别的区别以及可能出现的问题

    当两个或多个事务读入同一数据并修改,会发生丢失修改问题,前一个事务修改的结果会被后一事务所做的修改覆盖。 当一个事务修改某个数据后,另一事务对该数据进行了读取,由于某种原因 前一事务撤销 了对该数据的修改,即将修改后的数据恢复原值,相当于没有执行

    2024年02月07日
    浏览(61)
  • 事务的四个特性、四个隔离级别以及数据库的常用锁

    事务的四个特性、四个隔离级别以及数据库的常用锁 四大特性 事务的四大特性,通常被称为ACID特性,是数据库管理系统(DBMS)确保事务处理的关键属性。这四大特性分别是: 原子性(Atomicity): 原子性要求事务是一个不可分割的单位,要么全部执行,要么全部不执行。如

    2024年02月04日
    浏览(34)
  • MySQL数据库中,在读已提交和可重复读这两个不同事务隔离级别下幻读的区别

    在正式开始之前,先简单回顾一下并发事务存在的问题以及事务的隔离级别等内容。 1.1 并发事务存在的问题 当两个或者两个以上事务同时开启去处理同一个表的数据时,可能会存在以下的问题: 丢失修改 脏读 不可重复读 幻读 丢失修改 丢失修改是指当两个或多个事务更新

    2024年02月02日
    浏览(44)
  • 数据库隔离级别

    1.1 事务 事务只是一个改变,是一些操作的集合;用专业的术语讲,他就是一个程序的执行单元; 事务本身其实并不包含这4个特性 ,只是我们需要通过某些手段,尽可能的让这个执行单元满足这四个特性,那么我们就可以称它为一个事务,或者说是一个正确的事务,完美的

    2024年02月07日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包