聊聊数据库事物处理

1. 事物的4个基本特新

  1. 原子性

  2. 一致性

  3. 隔离性

  4. 持久性

2. 事物的隔离级别

  1. 场景:并发修改提交,脏数据

  2. 并发安全和性能互斥

隔离级别,由低到高的顺序是:

  1. 未提交读

  2. 读写提交

  3. 可重复读

  4. 串行话

  • 未提交读:一个事物可以读取到另一个事物没有提交的数据,出现脏读。危险,不使用。

  • 读写提交:一个事物只能读取另一个事物提交的数据,不能读取未提交的数据。不可重复读。

  • 可重复读:一个事物等待另一个事物提交后再读取。行锁。容易出现幻读。

  • 串行化:最高隔离级别,sql顺序执行,克服各种问题,保证数据的一致性。

现实中,隔离级别以读写提交为主,可以防止脏读,不能避免不可重复读和幻读。

为了克服数据不一致和性能问题,不再使用数据库而使用其他手段,redis分布式锁

3. 传播行为

传播行为是方法之间调用事物采用的策略,绝大部份情况下,我们认为数据库事物要么全部成功,要么全部失败。

一个方法调用另一个方法,涉及到传播行为。这些设置都是设置在另一个方法上的

  1. required(常用): 需要事物,默认的传播行为,如果当前存在事物就沿用当前的事物,否则新建一个事物运行子方法

  2. supports: 支持事物,如果当前存在事物,就沿用当前的事物,如果不存在,就继续采用无事物的方式运行子方法

  3. mandatory: 必须使用事物,如果当前没有事物就抛出异常,如果存在当前事物,就沿用当前事物

  4. requires_new(常用): 无论当前事物是否存在,都会创建新事物运行方法

  5. not_supported: 不支持事物,当前存在事物,将事物挂起运行方法

  6. never: 不支持事物,如果当前存在事物,就抛出异常,否则继续使用无事物机制运行

  7. nested(常用): 子方法发生异常,只会滚子方法执行过的sql,不回滚当前方法的事物

4. 自调用失效问题

同一个service中的两个方法,相互调用,事物失效

解决方法:

  1. 避免同一个serivce方法相互调用

  2. applicationcontext.getBean(UserService.class);获取bean,调用方法。

Last updated

Was this helpful?