赞
踩
MySQL基础知识:介绍MySQL数据库的基本概念和常用命令,如何创建数据库、表、用户和权限管理等。
MySQL安装教程:Centos7 安装MySQL5.7.29详细安装手册
MySQL数据类型:详细介绍MySQL支持的各种数据类型,如整型、字符型、日期时间型等,以及它们的存储和使用方法。
MySQL查询语句:详解MySQL查询语句:SELECT语句一网打尽。
MySQL事务管理:探索MySQL事务的奥秘:事务隔离级别、事务不生效原因详解。
MySQL性能优化:解锁MySQL性能的魔法:优化技巧大揭秘包括索引优化、失效原因、缓存策略、分区表等
MySQL高可用性:MySQL高可用性攻略:快速搭建MySQL主从复制集群 !
MySQL高频面试题大揭秘:通关攻略,涵盖丰富题型,面试必备!
MySQL作为最流行的关系型数据库之一,其事务支持功能十分强大,本文将深入探讨MySQL中事务的隔离级别、事务不生效原因。
事务是数据库中一系列操作的集合,这些操作要么全部成功执行,要么全部失败回滚。事务的四个关键特性通常被缩写为ACID:
介绍之前先说明下什么是脏读、不可重复读和幻读,它们是数据库中常见的并发问题,它们可能会影响事务的一致性。以下是对这三种问题的介绍:
脏读指的是一个事务读取了另一个事务未提交的数据。例如,事务A读取了事务B正在修改但尚未提交的数据,如果事务B回滚了,则事务A读取到的数据就是无效的,因此称为脏数据。
脏读问题会导致读取到不一致的数据,可能会产生错误的结果或不符合预期的行为。
不可重复读(Non-Repeatable Read):
不可重复读指的是在一个事务中,同一条记录在事务执行期间被另一个事务修改,导致多次读取同一条记录时得到的结果不一致。
例如,事务A首先读取了一条记录,然后事务B修改了该记录并提交,随后事务A再次读取同一条记录,发现其值已经发生了变化,这就是不可重复读问题。
不可重复读问题可能会导致事务的逻辑错误,破坏了事务的隔离性。
幻读(Phantom Read):
幻读指的是在一个事务中,同一查询条件下的结果集在事务执行期间被另一个事务插入或删除,导致多次查询同一数据集时得到的结果集不一致。
例如,事务A首先查询了一个范围内的数据,并对结果集进行操作,然后事务B插入了符合查询条件的新数据,接着事务A再次查询同一范围内的数据,发现结果集中出现了新插入的数据,这就是幻读问题。
幻读问题可能会导致事务的结果不可预测,破坏了事务的隔离性。
数据库事务的隔离级别是指多个事务之间的可见性和并发性的控制程度。MySQL支持四种标准的隔离级别,每种级别都具有不同的特性和影响。这些隔离级别包括:
Spring Boot提供了简单易用的方式来管理数据库事务。通过@Transactional注解,可以轻松地在Spring Boot应用中实现事务管理。例如:
import org.springframework.transaction.annotation.Transactional;
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
@Transactional
public void updateUser(User user) {
// 更新用户信息
userRepository.save(user);
}
// 其他业务方法
}
在以上示例中,@Transactional注解被应用在updateUser方法上,表示该方法应该在一个事务中执行。如果方法成功执行,则事务将被提交;如果方法出现异常,则事务将被回滚,数据库恢复到方法执行前的状态。
不过一般我们会配上spring事务的传播机制和回滚异常类
@Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = Exception.class)
名称 | 介绍 |
---|---|
PROPAGATION_REQUIRED | 支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。 |
PROPAGATION_SUPPORTS | 支持当前事务,如果当前没有事务,就以非事务方式执行。 |
PROPAGATION_MANDATORY | 支持当前事务,如果当前没有事务,就抛出异常。 |
PROPAGATION_REQUIRES_NEW | 新建事务,如果当前存在事务,把当前事务挂起。 |
PROPAGATION_NOT_SUPPORTED | 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。 |
PROPAGATION_NEVER | 以非事务方式执行,如果当前存在事务,则抛出异常。 |
PROPAGATION_NESTED | 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则进行与PROPAGATION_REQUIRED类似的操作。 |
当编写代码时,也有一些情况可能会导致事务不生效,以下是一些常见的情况:
@Service
public class MyService {
@Autowired
private MyRepository myRepository;
@Transactional
public void doSomething() {
// 这里的事务生效
myRepository.save(something);
// 这里的事务不生效
doAnotherThing(); // 没有通过代理调用该方法
}
public void doAnotherThing() {
// ...
}
}
@Service
public class MyService {
@Autowired
private MyRepository myRepository;
@Transactional
public void doSomething() {
// 这里的事务生效
myRepository.save(something);
// 这里的事务不生效
doAnotherThing(); // self-invocation
}
@Transactional
public void doAnotherThing() {
// ...
}
}
3. 捕获异常并不重新抛出:如果在事务方法中捕获了异常但没有重新抛出,事务将不会回滚。因为Spring事务管理器默认只捕获未被捕获的异常来触发事务回滚。
@Transactional
public void doSomething() {
try {
// 事务生效
// 一些操作
} catch (Exception e) {
// 异常被捕获,但不重新抛出
// 事务不会回滚
}
}
4. 方法调用时使用了线程池:如果在使用线程池的方法中调用了带有@Transactional注解的方法,事务将不会生效。这是因为Spring的事务管理器是基于线程本地变量实现的,当线程池中的线程复用时,事务上下文无法正确传播。
5. 非公共方法调用:如果在同一个类中调用了一个带有@Transactional注解的非公共方法,事务将不会生效。因为Spring AOP是基于代理的,默认情况下只能拦截公共方法。
@Service
public class MyService {
@Autowired
private MyRepository myRepository;
@Transactional
public void doSomething() {
// 这里的事务生效
myRepository.save(something);
// 这里的事务不生效
doAnotherThing(); // 非公共方法
}
@Transactional
private void doAnotherThing() {
// ...
}
}
以上是一些可能导致事务不生效的常见代码编写情况。在使用事务时,务必要注意这些问题,确保事务能够正确生效,以保障数据的一致性和完整性。
四、总结
本篇文章介绍到这里就结束了,希望对您有所帮助,另外有什么问题可以在评论区进行交流。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。