DB更新或插入实现方案对比

DB更新或插入实现方案对比

背景

工作中经常会遇到一些场景,需要DB中已存在某行记录时进行更新,如果不存在的话则进行新增插入。

方案对比

方案实现优点缺点说明
1insert … on DUPLICATE key update更新和新增在一个事务,且支持单条或者批量无论是否新增,只要触发就会使主键seq值自增,受主键的最大长度限制可使用bigint类型主键,最大表示19位,结合业务调用方控制必要时才触发此操作(如果下单置为老用户时先查询判断是老用户就不更新了),避免不必要的调用。但这个比较强依赖调用方。
2同一事务内:update + insert (update无变更行时表示无数据,进行新增)单条操作简单,并发安全,较好地避免无效调用带来的id自增问题批量实现不友好,批量更新时无法感知哪些更新成功哪些更新失败;悲观锁,效率较低。目前能做的:1. 利用mysql url的allowMultiQueries=true属性实现一次批量更新。2.批量插入。但无法准确对更新无记录的数据进行新增,要么就是代码中循环单条执行『更新+插入』。
3一锁二判三更新。同一事务内,select … for update查询加行锁,之后进行更新或者插入并发安全;根据查询结果可以知道哪些记录不存在需要插入,哪些记录存在需要更新。悲观锁,效率较低
4乐观锁:普通查询+插入或者利用版本号判断更新并发效率高且安全版本号更新失败需要重试,需要额外成本;例如重试3次,同时10个请求,最多只会成功3个,太多请求写同一数据一定有问题,拦截掉可行;版本号上限问题1.版本号更新失败的重试处理:同一用户对同一bizType的同一bizVal同时进行更新的概率不大,即用户不太可能同时在不同设备下相同的订单。2.版本号只有在更新成功时才会进行+1,这个上限由单个用户在同一店铺下的订单数决定,目前smallint类型,最大支持2^15-1(32767),结合目前业务量来讲够用,并且达到最大值更新失败后也不影响用户身份标识(三万多单一定是老用户了)。3.某条记录的版本号达到上限,也只会影响当前用户,不会像id一样影响所有数据

可以根据具体场景选择合适的方案,如有其他更好的方案,欢迎评论交流~

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值