MySQL--幂等

深碍√TFBOYSˉ_ 2023-07-19 04:48 26阅读 0赞

原文网址:MySQL—幂等_IT利刃出鞘的博客-CSDN博客_mysql幂等

其他网址

为什么需要幂等_数据库_Chaos Awakening-CSDN博客(有实例)

何为幂等?如何设计?_数据库_极客on之路-CSDN博客

简介

SQL幂等语句





























操作

是否幂等

实例

查询

幂等

select * from user where xxx

//不对数据产生任何变化

新增

幂等/不幂等 都有。

insert into user(userid,name) values(1,’a’),

若userid为唯一主键,即重复操作上面的业务,只会插入一条用户数据,具备幂等性。

若userid不是主键,可以重复,那上面业务多次操作,数据都会新增多条,不具备幂等性。

修改

幂等/不幂等 都有。

update user set point = 20 where userid=1

//直接赋值。不管执行多少次,point都一样,具备幂等性。

update user set point = point + 20 where userid=1

//计算赋值。每次操作point数据都不一样,不具备幂等性

删除

幂等

delete from user where userid=1

幂等方法





























方法

说明

优缺点

唯一主键

利用数据库的主键唯一约束,解决了在insert场景时幂等问题。

要求主键不是自增主键,需要业务生成全局唯一的主键

缺点:

1. 无法使用自增主键

2. 分库分表时使用不方便

乐观锁

乐观锁解决了计算赋值型的修改场景

示例:update user set point = point + 20, version = version + 1 where userid=1 and version=1

缺点:操作业务前,需要先查询出当前的version版本。

token

使用token+Redis

业务请求每次请求,都会有额外的请求

去重表

把唯一主键插入去重表,再进行业务操作,且他们在同一个事务中。这个保证了重复请求时,因为去重表有唯一约束,导致请求失败,避免了幂等问题。

唯一索引机制

当对有唯一索引约束的列插入同样的数据时会出错,所以可以基于此来进行幂等操作。
思路:对请求生成一个全局唯一ID,在执行操作前先插入全局唯一ID是否存在,如果能插入则说明是第一次请求,不能插入则说明是重复请求。

实例

  1. create table `tb`(
  2. `id` int(11) NOT NULL,
  3. `un` int(10),
  4. PRIMARY KEY(`id`)
  5. );
  6. alter table `tb` add unique (un);
  7. mysql> insert into tb(`id`, `un`) values(1, 1);
  8. Query OK, 1 row affected (0.11 sec)
  9. mysql> insert into tb(`id`, `un`) values(2, 1);
  10. ERROR 1062 (23000): Duplicate entry '1' for key 'un'
  11. mysql> insert into tb(`id`, `un`) values(1, 2);
  12. ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY'

注意

如果唯一索引不是主键,则主键可以使用自增主键;如果使用了自增主键,则不建议再将主键设置为要进行幂等操作的列(既想让主键自增又想给他指定值毕竟是不好的,虽然实际上也行得通)。

乐观锁机制

乐观锁这里解决了计算赋值型的修改场景。我们对之前的sql语句进行修改。

  1. update user set point = point + 20, version = version + 1 where userid=1 and version=1

加上了版本号后,就让此计算赋值型业务,具备了幂等性

乐观锁机制缺点:就是在操作业务前,需要先查询出当前的version版本

token机制

何为幂等?如何设计?

上图就是token+redis的幂等方案,适用绝大部分场景。主要思想:

1、服务端提供了发送token的接口。我们在分析业务的时候,哪些业务是存在幂等问题的,就必须在执行业务前,先去获取token,服务器会把token保存到redis中。(微服务肯定是分布式了,如果单机就适用jvm缓存)。

2、然后调用业务接口请求时,把token携带过去,一般放在请求头部。

3、服务器判断token是否存在redis中,存在表示第一次请求,可以继续执行业务,执行业务完成后,最后需要把redis中的token删除

4、如果判断token不存在redis中,就表示是重复操作,直接返回重复标记给client,这样就保证了业务代码,不被重复执行。

这种方案是比较常用的方案,也是网上经常介绍的,但是有一点不同的地方:

网上方案:检验token存在(表示第一次请求)后,就立刻删除token,再进行业务处理

上面方案:检验token存在(表示第一次请求)后,先进行业务处理,再删除token

关键点就是 先删除token,还是后删除token。

一、网上方案缺点

我们看下网上方案,先删除token,这是出现系统问题导致业务处理出现异常,业务处理没有成功,接口调用方也没有获取到明确的结果,然后进行重试,但token已经删除掉了,服务端判断token不存在,认为是重复请求,就直接返回了,无法进行业务处理了。

二、上面方案缺点

后删除token也是会存在问题的,如果进行业务处理成功后,删除redis中的token失败了,这样就导致了有可能会发生重复请求,因为token没有被删除

小伙伴们有没有发现,其实上面的问题就是数据库和缓存redis数据不一致的问题。

其实根据这个场景的业务,可以有个简单的处理方式。老顾推荐是网上方案先删除token,先保证不会因为重复请求,业务数据出现问题。顶多再让用户处理一次。

出现业务异常,可以让调用方配合处理一下,重新获取新的token,再次由业务调用方发起重试请求就ok了

token机制缺点

业务请求每次请求,都会有额外的请求(一次获取token请求、判断token是否存在的业务)。其实真实的生产环境中,1万请求也许只会存在10个左右的请求会发生重试,为了这10个请求,我们让9990个请求都发生了额外的请求。(当然redis性能很好,耗时不会太明显)

去重表机制

这个方案业务中要有唯一索引,这个去重表中只要一个字段就行,设置唯一索引约束(一般直接设为唯一主键即可),当然根据业务自行添加其他字段。主要流程如下图所示

何为幂等?如何设计?

上面的主要流程就是 把唯一主键插入去重表,再进行业务操作,且他们在同一个事务中。这个保证了重复请求时,因为去重表有唯一约束,导致请求失败,避免了幂等问题

这里要注意的是,去重表和业务表应该在同一库中,这样就保证了在同一个事务,即使业务操作失败了,也会把去重表的数据回滚。这个很好的保证了数据一致性

这个方案也是比较常用的,去重表是跟业务无关的,很多业务可以共用同一个去重表,只要规划好唯一主键就行了。

发表评论

表情:
评论列表 (有 0 条评论,26人围观)

还没有评论,来说两句吧...

相关阅读

    相关

    幂等性 1.什么是幂等性? 对于同一笔业务操作,不管调用多少次,得到的结果都是一样的。 2.幂等性技术方案 1.悲观锁 获取数据的时候加锁获取。sel

    相关 性实现 -接口

    接口幂等性 1.什么是幂等性 > 对于同一笔业务操作,不管调用多少次,得到的结果都是一样的。 > 也就是方法调用一次和调用多次产生的额外效果是相同的,他就具有幂

    相关

    老婆问了个问题,什么是“幂等性”?这个问题,从现象上好解释,例如今儿是618大促,购物车添加了丰富的商品,满心欢喜地点击了支付按钮,支付成 功了,但是返回的时候网络异常,不知道

    相关

    幂等:两次调用和一次调用没有什么区别。 在失败重试,和定时补偿的时候,一定要考虑幂等性,否则会导致库存锁定,库存释放,库存扣减,库存回滚失败。 库存锁定:提交订单锁定库存

    相关

    HTTP/1.1中对幂等性的定义是:一次和多次请求某一个资源对于资源本身应该具有同样的结果(网络超时等问题除外)。也就是说,其任意多次执行对资源本身所产生的影响均与一次执行的影