MaG*_*tas 17 mysql queue innodb laravel laravel-5
我正在使用Laravel 5.1.
队列用于在多个系统之间进行数据获取/同步.
我使用数据库驱动程序,3"artisan queue:work --daemon"进程一直在运行.
作业由系统用户和调度程序(cron)分派.三个队列用于确定作业的优先级.
一切似乎工作得很好 - 作业表充满了记录,系统负责处理它们并删除已完成的记录.
但是一段时间后锁定问题开始干扰:
SQLSTATE [40001]:序列化失败:1213尝试获取锁定时发现死锁; 尝试重新启动事务
和
'RuntimeException',消息'在事务中无法交换PDO实例'.
和
SQLSTATE [HY000]:常规错误:1205超出锁定等待超时; 尝试重新启动事务
我还没有尝试过使用其他队列驱动程序.我真的很想留在数据库中.引擎是InnoDB,jobs表有默认结构和索引.
有没有办法解决这个问题?你的想法是什么?
值得一提的是,DB::reconnect()因为队列工作程序作为守护进程运行,所以我在内部调用我的作业类.
DispatchesJobs正如人们所期望的那样,使用特征调度作业.我不以任何其他方式干扰队列算法.
这可能不是答案,而是一些信息。
\n\n使用SELECT ... FOR UPDATE语句时,您可能会观察到锁争用(死锁等)。
select \xe2\x80\xa6 for update where x <= y\nRun Code Online (Sandbox Code Playgroud)\n\n它的范围扫描 <=\n数据库会锁定所有 <= y 的行,包括任何间隙\n因此,如果您有像这样带有 y 的行: 1, 3, 5\nit 甚至会锁定索引中 1 和 3 之间的空白空间\nits 称为间隙锁定
\n\n可以使用此命令查看问题:
\n\nSHOW ENGINE INNODB STATUS;\n\n---TRANSACTION 72C, ACTIVE 755 sec\n4 lock struct(s), heap size 1248, 3 row lock(s), undo log entries 1\nMySQL thread id 3, OS thread handle 0x7f84a78ba700, query id 163 localhost msandbox\nTABLE LOCK table test.t trx id 72C lock mode IX\nRECORD LOCKS space id 19 page no 4 n bits 80 index age of table test.t trx id 72C lock_mode X\nRECORD LOCKS space id 19 page no 3 n bits 80 index GEN_CLUST_INDEX of table test.t trx id 72C lock_mode X locks rec but not gap\nRECORD LOCKS space id 19 page no 4 n bits 80 index age of table test.t trx id 72C lock_mode X locks gap before rec\nRun Code Online (Sandbox Code Playgroud)\n\n最后一行
\n\n如果事务中有很多间隙锁影响并发性和性能,您可以通过两种不同的方式禁用它们:
\n\n1- Change the ISOLATION level to READ COMMITTED. In this isolation level, it is normal and expected that query results can change during a transaction, so there is no need to create locks to prevent that from happening.\n\n2- innodb_locks_unsafe_for_binlog = 1. Disables the gap locks except for foreign-key constraint checking or duplicate-key checking.\nRun Code Online (Sandbox Code Playgroud)\n\nhttps://www.percona.com/blog/2012/03/27/innodbs-gap-locks/
\n