我有一个大约有5,000,000行的MySQL表,通过DBI连接的并行Perl进程以小的方式不断更新.该表有大约10列和几个索引.
一个相当常见的操作有时会产生以下错误:
DBD::mysql::st execute failed: Deadlock found when trying to get lock; try restarting transaction at Db.pm line 276.
Run Code Online (Sandbox Code Playgroud)
触发错误的SQL语句是这样的:
UPDATE file_table SET a_lock = 'process-1234' WHERE param1 = 'X' AND param2 = 'Y' AND param3 = 'Z' LIMIT 47
Run Code Online (Sandbox Code Playgroud)
该错误仅在有时触发.我估计只有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;
Run Code Online (Sandbox Code Playgroud)
我在网上看到其他几个人报告了类似的错误,这可能是一个真正的僵局.
我有两个问题:
究竟是什么情况导致上述错误?
有一种简单的方法来解决它或减少它的频率?例如,我究竟如何"在Db.pm第276行重新启动交易"?
提前致谢.