同一接口被多次请求,数据还未来得及入库导致数据不一致的问题

问题:

有一个接口,使用了事务,而且会自建数据,但是只能允许自建一种类型的数据。如果请求分开来,一次结束后接着第二次,那么就会如期只自建一个。但如果请求同时发起,同一种类型的就会出现多条自建数据。

原因:

在因为有个事务的原因,事务会完成之后再写入到数据库。这时候如果当前事务还没完成的时候,就进行第二次请求,就会导致查数据库的时候没有自建数据,然后这次请求也进行了自建,这样就导致了只允许自建一次的数据自建了两次。

解决方案:

开发中经常会遇到这种问题,主要核心在事务身上。事务注解里面有个值可以设定事务隔离级别,将事务隔离级别设为可以读取其他事务未提交的数据 就行了。

isolation : 事务的隔离级别 :

Isolation.DEFAULT:这是默认值,表示使用底层数据库的默认隔离级别。对大部分数据库而言,通常这值就是TransactionDefinition.ISOLATION.READ_COMMITTED(读已提交)。但是MySQL InnoDB 存储引擎的默认支持的隔离级别是 REPEATABLE-READ(可重读)。

TransactionDefinition.Isolation.READ_UNCOMMITTED(读取未提交):
该隔离级别表示一个事务可以读取另一个事务修改但还没有提交的数据。该级别不能防止脏读,不可重复读和幻读,因此很少使用该隔离级别。比如PostgreSQL实际上并没有此级别。

TransactionDefinition.Isolation.READ_COMMITTED(读取已提交):
该隔离级别表示一个事务只能读取另一个事务已经提交的数据。该级别可以防止脏读,这也是大多数情况下的推荐值。

TransactionDefinition.Isolation.REPEATABLE_READ(可重复读):
该隔离级别表示一个事务在整个过程中可以多次重复执行某个查询,并且每次返回的记录都相同。该级别可以防止脏读和不可重复读。

TransactionDefinition.Isolation.SERIALIZABLE(可串行化):最高的隔离级别,所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。但是这将严重影响程序的性能。

此时我就是设置的可读取未提及的数据

就解决了这个问题。

事务注解中还有其他的注释,下来可以看看,只是这个问题只需要用到这个注释而已。

但写到这时候我又发现个问题:如果读取其他事务未提交的数据时候,这边进行判断默认为已创建,但是之前那个请求发生了异常,这时候数据并没有提交,而第二次请求又是默认它提交了,这个时候就会出现bug。

这时候就有一个其他的注释了

Propagation : 事务的传播行为 

可以理解为当同时遇见两个事务的时的运行策略

默认值:Propagation.REQUIRED;如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。

Propagation.REQUIRES_NEW:创建一个新的事务,如果当前存在事务,则把当前事务挂起。

Propagation.SUPPORTS:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。

Propagation.NOT_SUPPORTED:以非事务方式运行,如果当前存在事务,则把当前事务挂起。

Propagation.NEVER:以非事务方式运行,如果当前存在事务,则抛出异常。

Propagation.MANDATORY:如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。

Propagation.NESTED:如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;

这个注释就很很明确了,如果有一个事务在进行中,下面这个事务该怎么进行。

总结:

看样子最方便的是选择嵌套运行,但如果是多个请求,不同类型的数据同时请求进来呢,这时候这两个事务没有必然关系,如果第一个请求发生了错误,回退了,那么后面这个事务也会跟着回退。这就会导致这一个事务回滚了,所有这同一时间进行的事务都回滚。

如果选择当前事务挂起,等待前面事务运行结束后再进行当前事务,这看起来是最严谨的,但会牺牲一些程序的性能,可能导致程序速度较慢。

具体使用策略还得看具体业务。

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值