两个业务,
一个业务多线程插入 N 条数据
另一个业务,多线程读取并删除 N 条数据 /或者使用 update 先修改数据加上唯一标签,然后读取,然后删除数据(update xxxx set use =1 token = uuid where use = 0 limit 100)
这两种读取并删除的方式
第一种方式要使用 for update 锁. 效率很低.
第二种方式使用 update 先修改数据,然后再删除数据,不用加锁,但是在多线程情况下效率更低,而且线程之间不会队列执行, 有的线程很快执行,有的会超时.
我考虑原因, 是 mysql 每个线程都会去数据的相同固定部分抓取数据
导致不管是 select 还是 update 都会冲突.
有没有更快的方式来实现这个功能呢? 什么类型的数据库,或者什么 sql 方案.
对 use 已经加索引了 但是加索引的作用不大, 我感觉 use 不是 0 就是 1 加了索引只是排除掉 use=1 的部分,这部分数据很少,use=0 的数据有几百万条. 但是 mysql 只会去头部取数据,导致冲突, 能不能让 mysql 每个任务都随机位置取数据呢.
业务需要统计数量等要求.所以不能用 list.
本人新手,表达能力不好,专业术语也不知道,实在抱歉,希望不吝赐教.
一个业务多线程插入 N 条数据
另一个业务,多线程读取并删除 N 条数据 /或者使用 update 先修改数据加上唯一标签,然后读取,然后删除数据(update xxxx set use =1 token = uuid where use = 0 limit 100)
这两种读取并删除的方式
第一种方式要使用 for update 锁. 效率很低.
第二种方式使用 update 先修改数据,然后再删除数据,不用加锁,但是在多线程情况下效率更低,而且线程之间不会队列执行, 有的线程很快执行,有的会超时.
我考虑原因, 是 mysql 每个线程都会去数据的相同固定部分抓取数据
导致不管是 select 还是 update 都会冲突.
有没有更快的方式来实现这个功能呢? 什么类型的数据库,或者什么 sql 方案.
对 use 已经加索引了 但是加索引的作用不大, 我感觉 use 不是 0 就是 1 加了索引只是排除掉 use=1 的部分,这部分数据很少,use=0 的数据有几百万条. 但是 mysql 只会去头部取数据,导致冲突, 能不能让 mysql 每个任务都随机位置取数据呢.
业务需要统计数量等要求.所以不能用 list.
本人新手,表达能力不好,专业术语也不知道,实在抱歉,希望不吝赐教.
5 条回复 • 2023-04-13 00:53:36 +08:00
|
1
iBugOne 2023 年 4 月 12 日 via Android
有没有可能你需要的东西不是 RDBMS ,而是一个消息队列
|
|
2
dreamkuo OP @iBugOne
感谢你的解答 ,我觉得也是,但是还有一些无法代替的功能, 比如说统计 use=1 use=0 的各自数量, 还有对于 use=1 的数据,修改为 use=0 (相当于回滚获取的数据.) |
|
3
imv2er 2023 年 4 月 12 日
如果是边插入边读取删除
插入的线程在插入完成后将主键值传递给读取删除的线程。 插入线程每次做批量插入,一次性提交。传递给后续线程也是一批一批的 读取删除的线程每次操作也是一个事务中的批量操作 无论删除和更新都要用主键作为 where 条件。 主键的传递可以考虑使用消息队列确保异常重启时不会遗漏没有读取的那部分。 如果是先插入后读取删除 那其实没啥好说的。 |