问题描述
问题-
在删除作业条目时,由于在JOBS表上造成死锁,我的工作人员失败了。
这种行为是经常发生的,即使流量略有增加。
需要避免这种死锁的建议吗?
配置-
-
使用Laravel队列和QUEUE_DRIVER = database
-
主管作为队列管理器
-
数据库是MySQL
日志-
{"message":"SQLSTATE[40001]: Serialization failure: 1213 Deadlock found when trying to get lock;
try restarting transaction (SQL: delete from `jobs` where `id` = 215520)","context":{"exception":{"class":"Illuminate\\Database\\QueryException","message":"SQLSTATE[40001]:
Serialization failure: 1213 Deadlock found when trying to get lock; try restarting transaction
(SQL: delete from `jobs` where `id` =
215520)","code":40001,"file":"/home/aditya/Desktop/code/Chqbook-
api/vendor/laravel/framework/src/Illuminate/Database/Connection.php:664","previous":
{"class":"PDOException","message":"SQLSTATE[40001]: Serialization failure: 1213 Deadlock found
when trying to get lock; try restarting
transaction","file":"/home/aditya/Desktop/code/Chqbook-
api/vendor/laravel/framework/src/Illuminate/Database/Connection.php:483"}}},"level":400,"level_n
ame":"ERROR","channel":"local","datetime":{"date":"2020-09-17
07:22:56.546154","timezone_type":3,"timezone":"Asia/Kolkata"},"extra":[]}
{"message":"SQLSTATE[HY000]: General error: 1205 Lock wait timeout exceeded; try restarting transaction (SQL: insert into `jobs` (`queue`,`attempts`,
解决方法
Taylor Otwell承认mysql从未打算用于队列。遇到此问题的原因可能有很多。
也许您应该考虑在队列中使用Redis而不是mysql(为什么不使用Horizon呢?
,死锁和锁定等待超时是相关的问题。
您有2个(或更多)连接,它们正在与同一张表的相同(或相邻)行做某事。
MySQL可能会采取两项措施:
- 停止一个连接,直到另一个释放行。如果释放花费的时间太长,则等待的连接将放弃“等待锁定超时”。故事的寓意:不要写花费超过几秒钟才能完成的事务:
- 如果每个人都在等待对方,则可能会出现“死锁”。一个连接的事务中止。使查询更快可以减少死锁的频率。准备重新执行事务是处理死锁的最终方法。
使用MySQL作为队列管理器会诱使您
- 从队列中获取项目
- 处理
- 从查询中删除项目
在事务中执行所有这三个步骤是合乎逻辑的。但是,如果步骤2花费了“很长时间”,则您正在乞求上面列出的问题之一。
更好的方法是:
BEGIN
1. Grab an item from the queue
2. Mark it as taken
COMMIT
3. Process it at your leisure
BEGIN
4. Remove the item from the queue
COMMIT