【问题标题】:Laravel worker failure because of Dead lock at JOBS table causing SQLSTATE[HY000]: General error: 1205 Lock wait timeout exceededLaravel worker 失败,因为 JOBS 表上的死锁导致 SQLSTATE [HY000]:一般错误:1205 Lock wait timeout exceeded
【发布时间】:2020-09-17 03:14:11
【问题描述】:

问题 -

在删除作业条目时,由于 JOBS 表出现死锁,我的工作人员失败了。

这种行为经常发生,即使流量略有增加。

需要建议来避免这种死锁吗?

配置-

  • 通过 QUEUE_DRIVER=database 使用 Laravel 队列

  • 作为队列管理员的主管

  • 数据库是 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","code":40001,"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`, 

【问题讨论】:

    标签: mysql laravel innodb supervisord


    【解决方案1】:

    Taylor Otwell 承认 mysql 从未打算用于队列。您遇到此问题的原因有很多。

    也许您应该考虑在队列中使用 Redis 而不是 mysql(为什么不使用 Horizo​​n,这太棒了)

    【讨论】:

    • 我正在尝试查找 Taylor Otwell admited that mysql was never intended to be used for queues. 的来源。请在 cmets 中提供相同的内容。谢谢!
    • Horizo​​n 用于监控队列和获取仪表板。这对这个问题有什么帮助?
    • 它没有,但如果你决定使用 Redis,让这个仪表板来监控你的所有工作很有趣
    • 我们不能。 REDIS 将所有内容都保存在 RAM 中,但我们的作业量超过了可用 RAM。
    【解决方案2】:

    死锁和锁等待超时是相关的问题。

    您有 2 个(或更多)连接正在对同一个表的相同(或相邻)行执行某些操作。

    MySQL 可能会采取两种行动:

    • 停止一个连接,直到另一个连接释放行。如果释放时间“太”长,则等待连接放弃“等待锁定超时”。故事的寓意:不要编写需要超过几秒钟才能完成的事务:
    • 如果每个人都在等待另一个人,那么您就有了“死锁”。一个连接的事务被中止。使查询更快可能会降低死锁的频率。准备好重新执行事务是处理死锁的终极方法。

    使用 MySQL 作为队列管理器很容易

    1. 从队列中获取一个项目
    2. 处理它
    3. 从查询中删除项目

    在事务中执行所有这 3 个步骤是合乎逻辑的。但是,如果第 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
    

    【讨论】:

    • 队列功能是框架驱动的。我无法控制它!
    • 或许有竞品?或者直接在 MySQL 中完成这项工作。
    • 您找到解决方案了吗?我们这里有同样的问题,我们不能再使用redis了
    • @realtebo - 您的情况可能略有不同。考虑开始一个单独的问题并提供更多详细信息。请在可行的情况下提供时间和 SQL。
    猜你喜欢
    • 2013-03-24
    • 2015-10-29
    • 2011-06-14
    • 2016-09-13
    • 2021-09-10
    • 1970-01-01
    • 2020-05-13
    • 2012-10-24
    相关资源
    最近更新 更多