我们最近看到很多错误:
ActiveRecord::TransactionIsolationConflict: Transaction isolation conflict detected: Lock wait timeout exceeded; try restarting transaction
无法弄清楚其背后的原因。但是在我们的代码中注意到一件事是试图锁定事务外的记录:
acc = Account.lock.find acc_id
上面的代码不在任何事务中,仅用于检查同样获得相同锁的其他事务是否已完成。如果这可能是罪魁祸首的任何想法?
答案 0 :(得分:1)
当巨大的写入负载时,InnoDB使用行级锁定来获得更好的并发性。引擎采取一些预防措施来摆脱幻像读取,其中之一是gap_lock,这可能导致这个问题。使用
SHOW ENGINE INNODB STATUS
分析gap_lock。
如果这有问题,您可以尝试以下选项
将ISOLATION
级别更改为READ COMMITTED
。
set innodb_locks_unsafe_for_binlog = 1
。除了外键约束检查或重复键检查外,这将禁用间隙锁。
再次使用show innodb status
来分析正在发生的事情。如果需要,请优化代码以避免锁定
如果以上操作不起作用,请尝试全局增加lock_wait_timeout
SET GLOBAL innodb_lock_wait_timeout = 120
;
或会议
SET innodb_lock_wait_timeout = 120;
再次检查您的配置,如果仍未更新,则再次设置全局变量
show variables like '%wait_timeout%';
show variables like '%tx_isolation%';
SELECT @@GLOBAL.tx_isolation, @@tx_isolation;
答案 1 :(得分:0)
请检查MySQL服务器上为innodb_lock_wait_timeout
和lock_wait_timeout
配置的内容。
您可以通过运行以下命令来执行此操作
show global variables like '%lock_wait_timeout';
正在使用哪些参数取决于您的MySQL版本和表格的引擎
来自文档:
#select *来自帐户,其中id = 1表示更新
Account.lock.find(1)
for update
表示 - 获取写入锁定。
您的交易可能需要比在数据库上配置的时间更长的时间,并且尝试验证原始交易的检查请求已完成 - 在等待的时间用完时收到此错误。