关于数据库高并发插入的版本号问题

2024-03-12 10:26:50 +08:00
 yevXxHmg

我的数据库设计的是如下格式 userid | business_type | config_id | total_version

(userid,business_type) 这两个的组合会控制 total_version 版本号字段,每次在对(userid,business_type)更新或者插入时,都会让 total_version 自增然后插入或者更新。 问题: 在高并发插入的情况下,我先获取(userid,business_type)的最大版本号,然后执行插入的这个过程,会导致多个插入记录同时都获取的 totoal_version= 1 然后两个都会执行 version + 1 = 2,导致用户版本号丢失一次更新记录。这个问题要怎么解决呢?

3643 次点击
所在节点    程序员
49 条回复
litguy
2024-03-12 17:21:39 +08:00
我们过去遇到类似的问题是这样处理的,仅供参考:
定义队列,所有插入放入队列,并不直接操作数据库
一个工作线程从队列取出来请求,插入数据库成功后把回调的 task 放到回调队列
回调队列工作线程执行回调
这样就不存在并发操作数据库的问题了
0X00FFFF
2024-03-12 17:26:48 +08:00
触发器
heiya
2024-03-12 17:48:22 +08:00
并发要求多少?这种共享变量的 读取-新增 操作不上锁都会有并发问题吧?可以试试把锁的粒度控制在最小,试试 select version from table where userid = ${} and business_type = ${} order by version limit 1 for update; where 条件字段要索引。
vczyh
2024-03-12 17:53:54 +08:00
我竟然没理解题目意思...
thevita
2024-03-12 17:53:59 +08:00
加个 current_version(user_id, business_type, current_version) 表,锁这个表来实现

inc current_version, 和 insert 放一个事务里,也不用去 max(version) 了-- 就是不知道业务有不有其他要求

-- 当然本质上跟 分布式锁,或者 redis 锁是一样的,开场景吧,我觉得大部分用不着分布式锁
heiya
2024-03-12 17:55:23 +08:00
@litguy 这个我感觉是相当于把所有的并发操作限制成了串行操作,是可以保证线程安全的,那效率怎么样呢?还有就是回调队列是干了什么事呢?
wu00
2024-03-12 18:13:51 +08:00
[quote]同一个用户账号在多端同时操作这个业务的配置信息[quote]
你这业务的粒度在 userid ,这怎么会有高并发呢,不要把并发和高并发一概而论哦。
你这个场景直接用乐观锁就行了,并发场景下只能成功一个,各大数据库应该都有 row version 的字段类型。
litguy
2024-03-12 18:57:13 +08:00
@heiya 你需要多高的插入性能,每秒 1W 够不够 ?如果可以接受,那就 OK 。回调是为了在别的线程处理剩下的事情,否则你需要的队列工作线程处理剩下的事情,会占据这个线程处理数据库写入的性能,放到队列,由回调处理线程处理就不存在这个问题了。
cnhongwei
2024-03-13 09:14:48 +08:00
userid 和 business_type 做唯一键,使用 INSERT INTO ON DUPLICATE KEY UPDATE 语句就行了。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://ex.noerr.eu.org/t/1022762

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX