- 事务概述
- 事务(Transaction)是指一组操作,这些操作要么全部成功执行,要么全部失败回滚
- 目的
- 保证数据的一致性和完整性,即使在出现错误或者系统崩溃的情况下,数据仍然保持正确状态
- 特性(ACID)
- 原子性(Atomicity)
- 事务中的所有操作要么全部执行成功,要么全部不执行
- 如果事务中的任何一个操作失败,整个事务将被回滚到事务开始之前的状态
- 一致性(Consistency)
- 事务执行前后,数据库必须保持一致状态
- 事务的执行不能破坏数据库的完整性约束
- 隔离性(Isolation)
- 多个事务同时执行时,一个事务的执行不应影响其他事务的执行结果
- 通常通过锁机制来实现事务的隔离性
- 持久性(Durability)
- 一旦事务提交,他所作的修改将永远保存到数据库
- 即使系统发生崩溃,这些修改也不会丢失
- 在Java中,事务管理通常由数据库管理系统(DBMS)和Java持久化框架(如JDBC、Hibernate、JPA等)共同实现。开发者可以使用这些工具来启动、提交和回滚事务
- 原子性(Atomicity)
- 事务并发会带来哪些问题
- 脏读(Dirty Read)
- 描述
- 一个事务读取了另一个事务尚未提交的更改
- 问题
- 如果第二个事务回滚,这些读取的数据将变的无效
- 影响
- 导致读取到的时间不真实,数据一致性被破坏
- 例子
- 事务A更新了一条记录的值
- 事务B读取了事务A更新后的值
- 事务B回滚 , 这样事务A读取到的数据就是无效的
- 描述
- 不可重复读(Non-Repeatable Read)
- 描述
- 在同一个事务中,两次读取同一数据得到不同的结果
- 问题
- 另一个事务在第一次读取后进行了修改 , 导致第二次读取的结果不同
- 影响
- 在同一事务内,多次读取同一记录得到不同结果,影响事务的逾期结果
- 例子
- 事务A读取一条记录的值
- 事务B更新这条记录并提交
- 事务A再次读取这条记录 , 发现值已经改变
- 描述
- 幻读(Phantom Read)
- 描述
- 一个事务在两次查询同一范围的数据时,第二次查询返回了新增或删除的数据
- 问题
- 另一个事务在第一次查询后插入或删除了数据,导致查询结果不一致。
- 影响
- 查询结果的记录数量或内容在同一事务内发生了变化,影响数据一致性
- 例子
- 事务A查询符合某个条件的记录集。
- 事务B插入或删除一些记录,影响了事务A的查询条件。
- 事务A再次查询时,结果集发生变化。
- 描述
- 丢失更新(Lost Update)
- 描述
- 两个事务同时读取同一数据,然后各自修改该数据并提交,导致其中一个修改被覆盖
- 问题
- 最后提交的修改会覆盖前一个事务的修改,导致数据丢失
- 例子
- 事务A和事务B同时读取某一记录的值。
- 事务A更新这条记录并提交。
- 事务B更新这条记录并提交,事务A的更新被覆盖。
- 描述
- 脏读(Dirty Read)
- 如何解决事务并发带来的问题(隔离级别)
- 数据库系统提供了不同的隔离级别来控制事务并发访问的数据一致性和性能的权衡
- 读未提交(Read Uncommitted)
- 允许
- 脏读
- 不可重复读
- 幻读
- 应用场景
- 最低的隔离级别,适用于对数据一致性要求低,追求最高性能的场景
- 影响
- 最容易出现并发问题,但性能最好
- 允许
- 读已提交(Read Committed)
- 解决
- 脏读
- 允许
- 不可重复读
- 幻读
- 应用场景
- 多数数据库的默认隔离级别 , 权衡了一定的性能和一致性
- 影响
- 避免了脏读,但仍可能出现不可重复读和幻读问题
- 解决
- 可重复读(Repeatable Read)
- 解决
- 脏读
- 不可重复读
- 允许
- 幻读
- 应用场景
- 适用于需要确保读取的数据在整个事务期间不变的场景
- 影响
- 避免了脏读和不可重复读问题,但可能出现幻读,数据一致性较高
- 解决
- 可串行化(Serializable)
- 解决
- 脏读
- 不可重复读
- 幻读
- 应用场景
- 最高的隔离级别,适用于对数据一致性要求极高的场景
- 影响
- 完全避免了并发问题,保证了最高的数据一致性,但性能最低,可能导致大量事务等待和锁竞争
- 解决
- MYSQL(隔离级别)
- 查看
- 查看当前会话的隔离级别
- SELECT @@SESSION.tx_isolation;
- 查看全局
- SELECT @@GLOBAL.tx_isolation;
- 或者在MySQL 8.0及以后的版本中:
- SELECT @@SESSION.transaction_isolation;
- SELECT @@GLOBAL.transaction_isolation;
- 查看当前会话的隔离级别
- 修改
- 修改当前会话的隔离级别
- SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
- SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
- SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
- SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
- 修改全局
- SET GLOBAL TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
- SET GLOBAL TRANSACTION ISOLATION LEVEL READ COMMITTED;
- SET GLOBAL TRANSACTION ISOLATION LEVEL REPEATABLE READ;
- SET GLOBAL TRANSACTION ISOLATION LEVEL SERIALIZABLE;
- 修改当前会话的隔离级别
- 注意事项
- 权限要求:更改全局隔离级别需要具有足够的权限(如超级用户权限)
- 事务内更改
- 如果在事务中更改隔离级别,通常会在事务结束时生效。
- 影响范围
- 修改全局隔离级别会影响所有新建立的会话,但不会影响已经存在的会话。修改会话隔离级别只影响当前会话
- 总结
- 通过查看和修改MySQL的事务隔离级别,可以灵活调整数据库系统的并发控制策略,从而在数据一致性和系统性能之间取得平衡。
- 根据具体的应用需求,合理选择适当的隔离级别,可以有效提高系统的可靠性和性能。
- 查看
- spring如何实现事务
- 编程式事务管理
- 编程式事务管理是指通过代码显式地管理事务。这种方式灵活性高,但代码侵入性强,不推荐在大型项目中广泛使用。
- 通过代码显式地管理事务,适用于需要精细控制的场景
- 声明式事务管理
- 声明式事务管理更为常用,它基于 AOP(面向切面编程),通过注解或 XML 配置来管理事务,减少了代码的侵入性。
- 事务jar包
- 依赖
- <!--spring事务依赖-->
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-tx</artifactId>
- <version>${spring.version}</version>
- </dependency>
- 依赖
- 修改配置文件
- <!--注入事务切面类 必须为transactionManager-->
- <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> </bean>
- <!--开启事务注解驱动-->
- <tx:annotation-driven/>
- <!--注入事务切面类 必须为transactionManager-->
- 使用事务注解
- @Transactional 可以用于类或方法上,用于声明在执行该方法或类中的所有方法时,应该进行事务管理
- 如果在类级别上使用 @Transactional 注解,则该类的所有公共方法都将具有相同的事务属性
- 编程式事务管理
JAVA事务,快速入门
于 2024-07-03 17:34:48 首次发布