今天下午,办公室的民工都在热火朝天的堆代码。突然前端的同志说,删除列表中的一些数据时会造成数据丢失或者重复,我有没有什么看法。作为一个资深不务正业的后端,我决定加入了这场讨论。
交代一下背景:用户个人中心的任务列表需要做批量删除,因为做了分页,根据 limit (page - 1) * page_size, page_size 确实会出现这样的问题。
数据举例:
page1:00 01 02 03 04 05 06 07 08 09
page2:10 11 12 13 14 15 16 17 18 19
page3:20 21 22 23 24 25 26 27 28 29
page4:30 31 32 33 34 35 36 37 38 39
page5:40 41 42 43 44 45 46 47 48 49
基于这样的背景我们 3 个人(分别称 A 、C 、D (本人),因为感觉小 B 不是很礼貌)提出了几种解决方案:
C:或许把删除先做成标记,等到用户退出列表页或者回到个人中心的时候再提交删除.
A & D:这样好像不太稳定,如果用户非正常退出的话不是很好正常提交,造成数据删除失败的现象,而且如果删除失败也不是很好的反馈给用户
D:把删除数据最上页的数据更新,下面的全删除掉呢 例:删除 11 22 23 30 这些数据的话,就重新加载 page2 ,page3 、4 、5 全都删掉。数据变为
page1:00 01 02 03 04 05 06 07 08 09
page2:10 12 13 14 15 16 17 18 19 20
A & C:这样用户体检不是很好,最好能定位到用户访问数据的最后一项
D:那删除之后,把最后一页做成补齐页记录误差,重新请求最后一页,创建一个新的页放进去呢 例:删除 11 22 23 30 这些数据的话,就把 page5 的前 4 个保留,删除掉后面 6 个,然后重新请求 page5 ,保存在 page6 ,记录误差为 1 ,数据变为
page1:00 01 02 03 04 05 06 07 08 09
page2:10 12 13 14 15 16 17 18 19
page3:20 21 24 25 26 27 28 29
page4: 31 32 33 34 35 36 37 38 39
page5:40 41 42 43
page6: 44 45 46 47 48 49 50 51 52 53
此时的 page6 的数据为 page5 的数据,page1 + ... + page5 是前 4 页的总和,误差记录为 1 ,请求时页码加上误差即可
A & C:这样会有点问题,如果删除的数据包括 page5 中的数据,那么补齐的数据需要去掉这些数据,如果删除的数据超过了一页,就需要计算最后几页,会比较麻烦
A:基于 3 的方法,在删除完成后把页码重新整合,再请求最后一页的数据,数据变为
page1:00 01 02 03 04 05 06 07 08 09
page2:10 12 13 14 15 16 17 18 19 20
page3: 21 24 25 26 27 28 29 31 32 33
page4: 34 35 36 37 38 39 40 41 42 43
page5: 44 45 46 47 48 49 50 51 52 53
C:可以请求的时候,加上 delete____count ,数据查询时变为 limit (page - 1) * page_size - delete_count, page_size
1.以上讨论都是建立用户操作自己的列表时所做的操作,而且没有考虑到多端登录的问题;
2.如果是在后台管理删除掉数据的话,用户的列表也会出问题,可能需要做缓存或者用别的方式通知用户?
3.想起之前做的竞价功能,需要最新的出价在上面,然后做分页,列表的数据也会用这种问题,如果加上请求时间就可以解决,如果有需要的同志可以这样实现。
好像还有很多的问题没有解决,但是今天有点晚了,就先这样。
第一次写这种主题,抛砖引玉,如果大家有什么好的解决方法欢迎一起讨论哈
1
baiyun 2022-09-16 00:51:42 +08:00 via iPhone
为什么删除数据会造成丢失或者重复显示?
|
2
baiyun 2022-09-16 00:54:35 +08:00 via iPhone
参考 ProTable 。前端处理基本都是固定的两种模式
|
3
renmu 2022-09-16 01:00:11 +08:00 via Android
按我的理解是 你们页面是无限滚动,然后删除之后导致分页出现问题了
|
4
akira 2022-09-16 01:00:23 +08:00
参考 gmail 批量删除时候的实现方案。要么就是基于当前页的手动选择,要么就是基于规则的选择,且规则选择会有上限。
|
5
edis0n0 2022-09-16 01:05:42 +08:00
我们这边的处理方案是任何场景下删除都只是隐藏,API 会返回已经删除的数据只是前端不显示给用户,然后弄个计划任务每天凌晨 4 点彻底删除 200 天前标记删除的内容。
|
6
Pastsong 2022-09-16 01:11:57 +08:00
不要传 page ,传 offset
|
7
CEBBCAT 2022-09-16 01:17:01 +08:00
需要清晰阐述一下业务模型。为什么会数据丢失或重复?每个条目的排序 ID 是不是都是单调递增的?
我猜楼主是瀑布流式列表?感觉产品太菜或者弱势。这种情况应该先决定能够接受的交互模型再设计实现方案。假如批量删除的条目直接抽空的话,页面会大幅度变化,用户还能记得刚才看到哪里吗? |
8
Building 2022-09-16 06:57:02 +08:00 via iPhone
前端数据和后端数据为什么非要耦合在一起? 前端取数据的时候应该用 cursor + offset
|
9
iam OP 统一回复一下对 “删除数据会造成丢失或者重复显示” 的疑问,哈哈,可能描述的不是很清晰。
前端请求数据的时候会传 page 和 page_size ,然后后端根据这个去查询。 SQL:select *** from *** where *** limit (page - 1) * page_size, page_size; 假如还是这些数据的话,在 page1 删除 00 ,那么前两页的数据就会变成 page1:01 02 03 04 05 06 07 08 09 10 page2:11 12 13 14 15 16 17 18 19 20 原 page1:00 01 02 03 04 05 06 07 08 09 因为已经渲染过,不做处理的话,就会造成 10 这条数据丢失。 如果是用户删除的,大家说的这些方式好像都可以解决,但是后台删除数据的话,还是会有这样的问题。 昨晚躺在床上想:在查询数据的时候需要传参开始访问时间,在这个时间之后删除的数据统计一下做一个偏移。 例: load_start_time = 2022 09 16 00:00:00;(请求参数) delete_count = select count(***) from *** where delete_time > load_start_time 不管是 offset 还是 page * page_szie , 游标都要向左偏移这个时间之后删除的数据条数 offset - delete_count |
10
xuanbg 2022-09-16 08:40:19 +08:00
无限滚动的数据按时间倒序分页的话,确实存在一个几乎无法解决的问题。就是数据发生变化后加载下一页数据,要么重复(添加数据,把最后一条数据挤到下一页了),要么丢数据(删除数据,下一条数据顶到上一页去了)。传 offset 也仅仅能解决只有一个用户在操作的情况,别人给你干掉一条数据,你的 offset 是不会变的。
唯一有效的办法是传当前页的最后一条数据的 id ,这要求 id 是自增或雪花 id 这种单调增长的。别无他法。 |
11
Moeyua 2022-09-16 09:44:13 +08:00
在页面加载时前端就「一次性」把数据全部获取下来,这里的「一次性」并不一定是一次请求,可以是多次请求,但重点是你要在用户删除数据前「主动」把所有数据加载完毕。之后前端自己做分页。
这种方法的缺陷就是不适用于非常大的数据量,而且无法感知到后台删除的数据。但话又说回来,如果后台删了一条用户已经渲染过的数据,这种情况真的是无解,处理起来相当复杂。 |
12
Moeyua 2022-09-16 09:49:36 +08:00
|
13
zhyl 2022-09-16 09:55:41 +08:00
介绍一下我的做法:前端表格列表同时只显示一页的数据,触发删除行为时,先在后端删除,然后前端手动移除这一项,如果这一页的数据都被移除了,重新请求接口拉取新的数据
|