两个队列任务同时操作一张表导致锁表,任务失败,请问如何解决?

两个队列任务同时操作一张表导致锁表,任务失败,请问如何解决?

Redis 队列两个任务有几率同时更新一张表数据,导致报错
Deadlock found when trying to get lock;try restarting transaction

应该是两个相同任务,同时执行,操作了同一个表,导致的,是我修复逻辑不让他们通知操作一张表,还是有办法,让他们可以同时操作同一张表?


// 下面这段代码按照条件筛选出的数据更新外键 
// 操作表 collect_data
$collect->where('keywords', '=', $goods_item['keywords'])
                    ->where('title', 'not like', '拍拍    %') // *** 搜索条件并非空格,是特殊字符(全角空格?) ***
                    ->where($orWhereBrand)
                    ->where($orWhereSKU)
                    ->where($whereFilter)
                    ->where($whereBlock)
                    ->where($orWhereShop)
                    ->where($whereShopBlock)
                    ->update(['goods_uuid' => $goods_item['uuid']]);

// 下面这段代码是更新主表商品状态,如果关联字表价格低于主表商品,商品状态更新为2 否则3 
// 主表 goods 子表 collect_data
            $update_sql = 'UPDATE ' . $goods_table . ' AS goods
                INNER JOIN (SELECT goods_uuid, MIN(price) price FROM ' . $collect_table . ' GROUP BY goods_uuid) AS collect_data
                ON goods.uuid = collect_data.goods_uuid
                SET goods.is_warning = IF(collect_data.price < goods.price, 2, 3)
                WHERE collect_data.goods_uuid = "' . $goods_item['uuid'] . '"';
            DB::update($update_sql);
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
最佳答案

发生这种情况可能是一个事务未提交(mysql 默认是开启自动提交事务的),另一个事务已经提交。导致的锁表或者锁行。

file

file

可以手动加锁,上一条未执行完毕,后面的需要等待。

可以使用 redis 加锁,然后队列中锁住的条件进行重试。条件用查询的唯一条件拼接。

这是之前参考论坛里大佬写的 service 你也可以参考一下。

代码已被折叠,点此展开
2年前 评论
zhy 2年前
zhy 2年前
ImVic (楼主) 2年前
看上隔壁小花了啦 (作者) 2年前
zhy 2年前
看上隔壁小花了啦 (作者) 2年前
讨论数量: 23

这个你最起码发下 sql 或者伪代码啊

2年前 评论
ImVic (楼主) 2年前
ImVic (楼主) 2年前

看代码没有锁表操作。

如果认为是锁表造成的队列,可以根据实际业务情况,对队列设置合理的重试次数以及重试规则。

例如,在队列确认是否是锁表造成的异常,则在 20 秒后进行重试处理。如果 3 次都因为同一问题失败,则标记为队列处理失败。

2年前 评论
ImVic (楼主) 2年前
ImVic (楼主) 2年前
24K大白羊 (作者) 2年前
ImVic (楼主) 2年前
zhy 2年前
ImVic (楼主) 2年前

我怎么觉得这种关联修改非常容易导致触发表锁呢?

2年前 评论

你的解释不对吧,想要避免冲突应该使用悲观锁。

2年前 评论

发生这种情况可能是一个事务未提交(mysql 默认是开启自动提交事务的),另一个事务已经提交。导致的锁表或者锁行。

file

file

可以手动加锁,上一条未执行完毕,后面的需要等待。

可以使用 redis 加锁,然后队列中锁住的条件进行重试。条件用查询的唯一条件拼接。

这是之前参考论坛里大佬写的 service 你也可以参考一下。

代码已被折叠,点此展开
2年前 评论
zhy 2年前
zhy 2年前
ImVic (楼主) 2年前
看上隔壁小花了啦 (作者) 2年前
zhy 2年前
看上隔壁小花了啦 (作者) 2年前

出现死锁了

2年前 评论

我觉得可以简单点,把表拆出来,两个字段分别对应两张表,和两个任务对应,这样执行就不会有锁表的问题了

2年前 评论

如果是 多任务频繁操作同一业务表,最好是通过 redis 来使用逻辑加 / 释放锁的操作来控制,,单单是让 mysql 的事务,肯定会经常发生死锁的

2年前 评论
yyy123456 2年前