java事务相关知识小总结
Spring 事务相关知识:
Spring提供了强大的事务管理机制,支持声明式事务和编程式事务。以下是一些与Spring事务相关的关键知识点:
声明式事务管理:
-
使用
@Transactional
注解声明事务,可以应用在类级别或方法级别。 -
提供了一系列的属性,如
propagation
(传播行为)、isolation
(隔离级别)、readOnly
(只读事务)、timeout
(超时设置)等。
@Service
@Transactional
public class MyService {// ...
}
编程式事务管理:
-
使用
TransactionTemplate
或PlatformTransactionManager
进行编程式事务管理。
@Service
public class MyService {
private final PlatformTransactionManager transactionManager;
@Autowiredpublic MyService(PlatformTransactionManager transactionManager) {this.transactionManager = transactionManager;}
public void programmaticTransaction() {TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager);transactionTemplate.execute(status -> {// your transactional codereturn null;});}
}
事务传播行为:
Spring 提供了多种事务传播行为,常用的包括:
-
REQUIRED(默认):
-
如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。
-
-
REQUIRES_NEW:
-
总是创建一个新的事务。如果当前存在事务,则将当前事务挂起。
-
-
NESTED:
-
如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则行为类似于
REQUIRED
。
-
-
SUPPORTS:
-
支持当前事务,如果没有当前事务,则以非事务方式执行。
-
-
NOT_SUPPORTED:
-
以非事务方式执行,如果当前存在事务,则将其挂起。
-
-
NEVER:
-
以非事务方式执行,如果当前存在事务,则抛出异常。
-
-
MANDATORY:
-
强制要求存在一个事务,如果没有,则抛出异常。
-
-
NEVER:
-
总是以非事务方式执行,如果当前存在事务,则抛出异常。
-
事务隔离级别:
-
DEFAULT:
-
使用数据库默认的隔离级别。
-
-
READ_UNCOMMITTED:
-
允许脏读、不可重复读、幻读。
-
-
READ_COMMITTED:
-
禁止脏读,但允许不可重复读、幻读。
-
-
REPEATABLE_READ:
-
禁止脏读、不可重复读,但允许幻读。
-
-
SERIALIZABLE:
-
禁止脏读、不可重复读、幻读。
-
事务的失效条件:
事务的失效是指在一些情况下,尽管使用了事务管理机制,但事务并未按照期望的方式工作。以下是一些可能导致事务失效的常见原因:
-
未捕获的异常:
-
如果在事务中的代码块中抛出未捕获的异常,并且这个异常不是继承自
RuntimeException
,Spring 的事务管理机制可能无法感知到异常,从而导致事务无法回滚。
-
-
自调用问题:
-
在同一类中,使用
this
关键字进行方法调用时,事务失效,因为默认是通过代理对象来增强事务的。
@Service @Transactional public class MyService { public void outerMethod() {innerMethod(); // 调用自己类中的方法} public void innerMethod() {// ...} }
-
-
不在公共方法上使用事务注解:
-
如果在非公共方法上使用
@Transactional
注解,事务也会失效,因为Spring AOP 默认只拦截公共方法。
@Service public class MyService { @Transactionalpublic void publicMethod() {// ...} @Transactionalprivate void privateMethod() {// 不会生效} }
-
-
事务的配置问题:
-
检查事务的配置,如传播行为、隔离级别等,确保其符合业务需求。
-
-
数据库引擎不支持事务:
-
确保数据库引擎支持事务,以及相关表的存储引擎是否支持事务。
-
在使用事务时,需要仔细检查代码和配置,确保事务的正确性。阅读日志和检查异常信息有助于识别和解决事务失效的问题。
MySQL 事务的相关知识:
MySQL 是一种支持事务的关系型数据库管理系统(RDBMS)。以下是一些关于 MySQL 事务的基本知识:
事务的四个特性(ACID):
-
原子性(Atomicity): 事务中的所有操作要么全部执行成功,要么全部失败回滚。
-
一致性(Consistency): 事务执行后,数据库从一个一致性状态转移到另一个一致性状态。
-
隔离性(Isolation): 多个事务同时执行时,一个事务的执行不应影响其他事务。
-
持久性(Durability): 一旦事务提交,其结果应该在数据库中持久存在,即使系统故障。
事务的隔离级别:
-
MySQL 支持多种隔离级别,包括读未提交(READ UNCOMMITTED)、读提交(READ COMMITTED)、可重复读(REPEATABLE READ)和串行化(SERIALIZABLE)。
事务的开始和提交:
-
使用
START TRANSACTION
或BEGIN
开始事务,使用COMMIT
提交事务。也可以使用ROLLBACK
进行事务回滚。
START TRANSACTION;
-- or BEGIN;
-- your SQL statements
COMMIT;
-- or ROLLBACK;
事务的自动提交:
-
默认情况下,MySQL 是自动提交事务的,每个 SQL 语句都被视为一个事务。可以使用
SET AUTOCOMMIT = 0
关闭自动提交,然后使用COMMIT
或ROLLBACK
手动管理事务。
SET AUTOCOMMIT = 0;
-- your SQL statements
COMMIT;
-- or ROLLBACK;
MySQL 事务的失效条件:
MySQL 事务的失效条件可能包括以下情况:
-
隔离级别问题:
-
在较低的隔离级别下,可能发生脏读、不可重复读或幻读。选择合适的隔离级别,根据业务需求来平衡一致性和性能。
-
-
死锁:
-
多个事务相互等待对方释放锁,导致所有事务都无法继续执行。
-
-
锁超时:
-
如果事务持有锁的时间过长,可能会导致其他事务因为等待超时而失败。
-
-
事务太大:
-
如果一个事务包含大量的数据修改,可能会导致锁定太多的资源,影响其他事务的执行。
-
-
并发性问题:
-
当大量并发事务同时访问数据库时,可能会出现性能问题,需要适当调整事务隔离级别和优化 SQL 查询。
-
-
数据库故障:
-
数据库的故障可能导致事务无法正常提交,需要合适的异常处理和重试机制。
-
Redis 事务的相关知识:
在 Redis 中,事务是通过 MULTI
、EXEC
、DISCARD
和 WATCH
等命令实现的。
-
MULTI: 开始一个事务,之后的命令都将被放入队列而不会立即执行。
-
EXEC: 执行所有在 MULTI 开始和 EXEC 结束之间的命令。
-
DISCARD: 取消事务,清空所有在 MULTI 开始和 DISCARD 结束之间的命令。
-
WATCH: 监视一个或多个键,当这些键被其他客户端修改时,事务将被取消。
事务的基本使用示例:
MULTI
SET key1 "value1"
GET key1
INCR key2
EXEC
以上命令会将 SET
、GET
和 INCR
三个命令作为一个事务进行处理。
Redis 事务的失效条件:
在 Redis 中,虽然有事务的概念,但 Redis 事务并不支持像关系型数据库那样的 ACID 特性。以下是一些 Redis 事务可能失效的情况:
-
WATCH 机制的限制:
-
Redis 使用 WATCH 命令来实现乐观锁,但 WATCH 只能监视字符串类型的键,不能监视集合或哈希表。
-
-
命令执行失败:
-
如果在 MULTI 和 EXEC 之间有命令执行失败,整个事务都不会回滚。Redis 事务并不具备回滚的能力。
-
-
命令语法错误:
-
如果在事务中存在语法错误的命令,整个事务将中断,后续命令不会执行。
-
-
执行命令失败:
-
如果在 EXEC 执行时,其中一个命令执行失败(比如对字符串类型执行了非字符串类型的命令),整个事务将中断。
-
-
网络问题:
-
在 EXEC 执行之前,如果与 Redis 服务器的连接断开,事务也会中断。
-
-
WATCH 的 CAS 版本冲突:
-
如果使用 WATCH 监控了某个键,但在执行 EXEC 时发现键的 CAS 版本已经发生了变化,事务也会中断。
-
需要注意的是,Redis 事务并不提供回滚的能力,而是执行到出错的那一步,之后的命令不再执行。因此,在使用 Redis 事务时,需要谨慎考虑其适用场景和特性。如果需要严格的事务控制,可能需要考虑其他数据库方案。
MyBatis 事务的相关知识:
MyBatis 是一个持久层框架,它允许开发者使用简单的 XML 或注解配置来映射原生信息,将 Java 对象映射到数据库表中。MyBatis 不直接处理事务,而是依赖于底层的数据库事务。
事务配置:
-
在 MyBatis 中,事务的管理通常交由底层的数据库连接池(如 Druid、HikariCP)来处理。MyBatis 不提供自己的事务管理器,而是通过配置数据源和使用 JDBC 事务。
<!-- MyBatis 配置文件 -->
<configuration><!-- 数据源配置 --><dataSource type="POOLED"><!-- 配置数据源相关信息 --></dataSource>
</configuration>
事务控制:
-
在 MyBatis 中,可以使用
@Transactional
注解来声明事务。这个注解可以在类级别或方法级别使用。
@Service
@Transactional
public class MyService {// ...
}
javaCopy code@Mapper
public interface MyMapper {@Transactionalvoid myMethod();
}
手动提交和回滚:
-
MyBatis 默认是开启自动提交的,如果需要手动控制事务,可以在
SqlSession
中使用commit()
和rollback()
方法。
SqlSession sqlSession = sqlSessionFactory.openSession();
try {// your codesqlSession.commit(); // 提交事务
} catch (Exception e) {sqlSession.rollback(); // 回滚事务
} finally {sqlSession.close();
}
MyBatis 事务的失效条件:
MyBatis 事务失效可能与底层数据库事务相关,常见的失效条件包括:
-
异常未捕获:
-
如果在事务中的代码块中抛出未捕获的异常,事务可能会失效。确保在事务代码块中适当地捕获和处理异常。
-
-
未设置自动提交:
-
默认情况下,MyBatis 是开启自动提交的。如果手动设置了
autoCommit
为false
,但没有手动提交事务,可能会导致事务失效。
sqlSession.getConnection().setAutoCommit(false);
-
-
手动提交后的继续执行:
-
如果在手动提交事务后继续执行其他 SQL 语句,可能会导致事务失效。确保在提交事务后不再执行其他需要事务保护的操作。
sqlSession.commit(); // 继续执行其他 SQL 语句
-
-
并发控制问题:
-
MyBatis 默认是不处理并发控制的,如果有多个线程同时修改同一行数据,可能会出现并发问题。在需要并发控制的场景,可以考虑使用数据库提供的锁机制或乐观锁。
-
确保了解 MyBatis 事务的底层机制,并在代码中正确地使用事务管理,可以避免事务失效的问题。在处理异常和提交事务时,要特别注意保持事务的一致性。