请教下 lockForUpdate () 的问题

情况

在循环执行更新数据的场景下:
table A
data a
data b
data c
data d
…..

这时候取出一条数据(data a)执行数据更新,比如要执行10s。
而2s后,脚本再次触发执行,这时候,还是取出了data a,又被执行了,造成资源浪费。

问题

所以我想,能不能从数据库层面限制掉这种重复取data a的情况,
table A
data a 上锁处理data a
data b
data c
data d
…..
这时候脚本执行只能取出data b,而我在事务里使用lockForUpdate(),脚本在再次执行的时候,会产生阻塞,导致超时。
请教大佬们,有办法解决这个问题吗?
PS:缓存肯定可行,只是想在数据库层面限制掉

本作品采用《CC 协议》,转载必须注明作者和本文链接
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
讨论数量: 5

:joy:串行化锁超时是在所难免的

3年前 评论

你是又想上锁,又不想阻塞,哪有这么好的事情

3年前 评论

简单点用缓存就好,更新中的都在缓存中记录,下次触发时查询从缓存中排除,更新完移除缓存。

3年前 评论

我在想有没有什么办法可以检测目标数据是否上锁

3年前 评论

虽然你没说,但从你的语境中的猜测数据库指的是mysql数据库。

好,那么就针对mysql来探讨一下这个问题。(接下来的讨论,我们默认是mysql5.5以上的 InnoDB引擎)

这时候取出一条数据(data a)执行数据更新,比如要执行 10s。

我感觉潜在的问题是你认为资源浪费了对吧。那么在这个场景下,我们来逐步分析一波。

我们知道mysql是基于磁盘的数据库,取出data a在操作系统下的步骤是,把磁盘的数据读入内存,再交给cpu去操作。从磁盘读数据是,随机I/O,代价非常高(即使是ssd,在第一次读取的时候依旧是随机)。mysql的做法通常不是只取data a,把data a左右的邻居也一起请到了内存来(这里是page的概念),然后只返回给你了data a这个东西。是的,操作好像就结束了。

那么

2s 后,脚本再次触发执行,这时候,还是取出了 data a,又被执行了,造成资源浪费。

这个步骤是怎么操作的呢?mysql直接从内存中把data a返回给你,效率非常之高。等等,为什么是直接从内存返回?因为mysql深知磁盘之慢,你上次查询的结果,它全部保存在内存中。即使你连续十次读取data a,从磁盘去读data a的动作也只有一次,剩下的九次都是在内存取。

在你提出的场景中,还是取出了 data a的速度超快,因为数据取自内存。好了,数据库层面不存在资源浪费了。

如果你是因为资源浪费,所以才要限制掉这种重复取 data a 的情况,那么讨论就已经可以结束了。如果你只是单纯想要限制重复取data a,那么我们应该怎么办。

这个在数据库层面是办不到的,或是我不知道。但在代码逻辑中是可以很轻松办到的,比如我们采取单例模式的设计,脚本运行的时候去redis查有没有一个特定的key,没有的话就设置一个,再脚本结束了再删除这个key。如果有这个特定的key,就结束脚本不执行。如果当前系统有队列,那么用队列去做也是一个不错的选择。解决方案很多,就看你怎么去选择。

3年前 评论
xujinhuan 3年前

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!