我有一个 MySQL 表,其中包含大约 5,000,000 行,这些行通过 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 行重新启动事务”?
提前致谢。