数据库并发问题和事务隔离界别

一、数据库的并发问题

1. 脏读

对于两个事务A,B,A读取了B更新的数据,但是B没有commit

2. 不可重复读

A读取了一个字段,然后B更新了这个字段,接着A再次读取这个字段。这样A就获取到了两个不同的字段

3. 幻读

A事务select了数据,然后B事务insert了,A再次select的话和第一次结果不一样

二、事务隔离界别

MySQL数据库事务要完成的目标:

  • 原子性(atomicity): 指所有在事务中的操作要么都成功,要么都不成功,所有的操作都不可分割,没有中间状态。一旦某一步执行失败,就会全部回滚到初始状态。
  • 一致性(consistency): 指的是逻辑上的一致性,即所有操作是符合现实当中的期望的
  • 隔离性(isolation): 即不同事务之间的相互影响和隔离的程度。比如,不同的隔离级别,事务的并发程度也不同,最强的隔离状态是所有的事务都是串行化的(serializable)(即一个事务完成之后才能进行下一个事务),这样并发性也会降到最低,在保证了强一致性的情况下,性能也会受很大影响,所以在实际工程当中,往往会折中一下。
  • 持久性(durability): 可以简单地理解为事务执行完毕后数据 不可逆并持久化存储 于存储系统当中

1. Read Uncommited:读未提交的数据

允许事务读取未被其他事务提交的数据。脏读、不可重复读、幻读三个问题都存在

2. Read Commit:读已提交的数据

允许事务读其他事务已经提交的数据。只可以避免脏读

3. Repeatable Read:可重复读

当前事务可以重复读取某个字段,实现方式就是禁止其他事务对这个字段的更新操作。遗留了幻读的问题

4. Serializable: 串行

事务可以从一个表中读物相同的行,实现方式是在这个事务执行期间,禁止其他事务对该表进行insert、update、delete

三、查看事务

事务级别越高,问题越少,但是性能越差。MySQL innodb默认事务隔离级别是RR(repeatable read)。

-- 查看当前会话bai隔离级别
select @@tx_isolation;

-- 设置当前会话隔离级别(read uncommitted, read committed, repeatable read, serializable)
set session transaction isolatin level repeatable read;

-- 查看系统当前隔离级别du
select @@global.tx_isolation;

-- 设置系统当前隔离级别
set global transaction isolation level repeatable read;

-- 事务使用
begin;
rollback;
commit;
Spring中的事务隔离级别是指在处理事务数据库管理系统(DBMS)如何管理并发访问的数据的一组规则,这确保了数据的一致性和完整性不被破坏。在使用Spring管理事务时,可以通过配置来选择不同的隔离级别。 ### Spring事务隔离级别的类型 #### READ UNCOMMITTED (读未提交) 这种隔离级别是最低级别的隔离模式,它允许读取到其他事务尚未提交的数据。这意味着可能出现不可重复读和幻读的问题,因为两个相同的查询可能返回不同结果。尽管效率最高但安全性最低,因此很少使用于生产环境。 #### READ COMMITTED (读已提交) 这是大多数关系型数据库默认的隔离级别。它确保在同一时间只有一个事务能够修改某个记录,从而避免脏读。但是,仍然存在非重复读的可能性,即同一个事务的不同执行阶段可能对相同数据产生不同的读取结果。 #### REPEATABLE READ (可重读) 在这个隔离级别下,一个事务的所有操作都是在一系列相同的快照中进行,直到该事务结束。这意味着两次相同的查询将始终返回相同的行集,有效防止了非重复读。然而,仍然可能存在幻读的情况。 #### SERIALIZABLE (可串行化) 这是最强的隔离级别,它通过强制事务按顺序执行来保证没有数据竞争情况发生。每个事务都像是在自己的线程中运行一样,不会影响到其他的事务。这种方式能彻底避免脏读、不可重复读以及幻读,但可能会显著降低系统的并发性能。 ### 如何配置Spring中的事务隔离级别 在Spring中配置事务隔离级别,通常是在配置`DataSource`或`TransactionManager`的时候。例如,如果你使用的是MyBatis和Spring整合的话: ```java @Configuration @EnableTransactionManagement public class TransactionConfig { @Bean public DataSource dataSource() { // 数据源配置 } @Bean public LocalContainerEntityManagerFactoryBean entityManagerFactory() { // Hibernate 或 JPA 配置 } @Bean public PlatformTransactionManager transactionManager() { return new DataSourceTransactionManager(dataSource()); } } ``` 然后在`application.properties`文件里设置`spring.datasource.hikari.isolation-level`为对应的隔离级别名称,比如`SERIALIZABLE`、`REPEATABLE_READ`等: ```properties spring.datasource.hikari.isolation-level=REPEATABLE_READ ``` ### 相关问题 1. **READ UNCOMMITTED 和 READ COMMITTED 的区别是什么?** 2. **为什么选择 REPEATABLE READ 而不是 READ COMMITTED?** 3. **SERIALIZABLE 是如何保证事务间的完全隔离性的?** 4. **在什么场景下推荐使用特定的事务隔离级别?**
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值