所有分类
  • 所有分类
  • 未分类

数据库-幂等-方案

简介

本文介绍数据库如何处理幂等。包括:SQL幂等语句有哪些,幂等的方案。

幂等性:多次调用方法或者接口不会改变业务状态(重复调用的结果和单次调用的结果一致)。
比如:用户注册、用户创建商品等操作,前端会提交数据给后台,后台根据提交的数据在数据库中创建记录。 如果用户不小心多点了几次,后端收到了多次提交,这时就会在数据库中重复创建了多条记录。

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场景时幂等问题。 业务生成全局唯一的值。 通常使用唯一主键索引。优点:实现很简单
乐观锁乐观锁解决了计算赋值型的修改场景 示例:UPDATE user SET point = point + 20, version = version + 1 WHERE userid=1 AND version=1缺点:操作业务前,需要先查询出当前的version版本。
token使用token + Redis缺点:业务请求每次请求,都会有额外的请求
去重表把唯一主键插入去重表,再进行业务操作,且他们在同一个事务中。这个保证了重复请求时,因为去重表有唯一约束,导致请求失败,避免了幂等问题。

方案1:唯一索引(推荐)

说明

当对有唯一索引约束的列插入同样的数据时会出错,所以可以基于此来进行幂等操作。

思路

对请求生成一个全局唯一ID,在执行操作前先插入全局唯一ID是否存在,如果能插入则说明是第一次请求,不能插入则说明是重复请求。

实例

create table `tb`(
	`id` int(11) NOT NULL,
	`un` int(10),
	PRIMARY KEY(`id`)
);

alter table `tb` add unique (un);

mysql> insert into tb(`id`, `un`) values(1, 1);
Query OK, 1 row affected (0.11 sec)
mysql> insert into tb(`id`, `un`) values(2, 1);
ERROR 1062 (23000): Duplicate entry '1' for key 'un'
mysql> insert into tb(`id`, `un`) values(1, 2);
ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY'

方案2:分布式锁(推荐)

可以用Redis分布式锁,锁的key为当前的Controller信息和入参信息。

  1. 如果Redis中还没有,表示还没有请求,将信息写到Redis,然后执行代码,执行结束后删除Redis数据。
  2. 如果Redis中已经有了,表示已经请求,直接报错。

详见:一个注解实现Redisson分布式锁 – 自学精灵

方案3:乐观锁

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

UPDATE user SET point = point + 20, version = version + 1 WHERE userid=1 AND version=1

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

乐观锁机制缺点:在操作业务前,需要先查询出当前的version版本。如果SQL有很多,改起来相当麻烦。

方案4:去重表

业务表要有唯一的列,将这个唯一的列放到去重表中,设置唯一索引约束

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

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

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

4

评论2

请先

  1. 去重表的图看起来不太对
    lxj_wzl 2024-01-02 0
    • 这种不太常用,大致了解应该就行。
      自学精灵 2024-01-02 0
显示验证码
没有账号?注册  忘记密码?

社交账号快速登录