我有一个MySQL表格,其中包含约500万行数据,这些数据通过使用DBI连接的并行Perl进程进行小规模更新。该表格有大约10个列和多个索引。
有一个相当常见的操作有时会出现以下错误:
DBD::mysql::st execute failed: Deadlock found when trying to get lock; try restarting transaction at Db.pm line 276.
导致错误的 SQL 语句大致如下:
UPDATE file_table SET a_lock = 'process-1234' WHERE param1 = 'X' AND param2 = 'Y' AND param3 = 'Z' LIMIT 47
错误只有在某些情况下才会被触发。我估计只有1%或更少的调用会出现这种情况。然而,在使用小表时从未发生过,随着数据库的增长,这种情况变得越来越普遍。
请注意,我在file_table中使用a_lock字段确保我运行的四个几乎相同的进程不会尝试处理同一行。这个限制被设计成将它们的工作分成小块。
我没有对MySQL或DBD::mysql进行过多的调整。MySQL是一个标准的Solaris部署,数据库连接如下所示:
my $dsn = "DBI:mysql:database=" . $DbConfig::database . ";host=${DbConfig::hostname};port=${DbConfig::port}";
my $dbh = DBI->connect($dsn, $DbConfig::username, $DbConfig::password, { RaiseError => 1, AutoCommit => 1 }) or die $DBI::errstr;
我在网上看到很多人报告了类似的错误,可能是真正的死锁情况。
我的问题有两个:
我的情况具体导致了上述错误?
有没有简单的方法来解决它或减少它的频率?例如,如何精确地执行“在Db.pm的第276行重启事务”?
提前感谢。
SHOW ENGINE INNODB STATUS
。 - Ryan Shillington