<分区>
我需要同时将 55 个 .tsv 文件中的数据导入 MySQL 数据库。
我的工作是使用 updateOrCreate() 方法读取文件并更新数据库中的行。
我的主管配置:
[program:laravel-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /Users/denis/Code/my_project/artisan queue:work --tries=3 --timeout=3600 --daemon
autostart=true
autorestart=true
numprocs=55
stdout_logfile=/Users/denis/Code/my_project/storage/logs/workers.log
stderr_logfile=/Users/denis/Code/my_project/storage/logs/workers_error.log
但是当我这样做时,所有作业都失败并出现错误:
PDOException: SQLSTATE[40001]: Serialization failure: 1213 Deadlock found when trying to get lock; try restarting transaction in /Users/denis/Code/my_project/vendor/laravel/framework/src/Illuminate/Database/Connection.php:474 ...
我可以用 try-catch block 解决它
$updated = null;
$db_max_retries = 10;
$db_retry_count = 0;
while($updated == null && $db_retry_count < $db_max_retries) {
try {
$updated = AdsPerformance::updateOrCreate(['campaign_id' => $performance_obj['campaign_id'], 'date' => $performance_obj['date'], 'ad_provider' => 'adwords'], $performance_obj);
} catch (\Exception $e) {
sleep(1);
$db_retry_count++;
}
}
$lines_proceded++;
... 但在这种情况下,该过程需要很长时间,因为在大约 2000 行导入行中有大约 200 个死锁。
- 当表为空时,不存在死锁。死锁仅在表已经有数据时出现(基本上是在尝试更新时)
- 我尝试使用不同的 sleep 时间。 sleep=5 时,死锁更少。使用 sleep=1/10 秒(我使用了 usleep(100000))会出现更多死锁。顺便说一句,在这些情况下,总执行时间差别不大。
- 我尝试使用其他队列驱动程序(redis 和 beanstalkd)。但也没有太大区别。
也许我可以尝试其他解决方案?像一些 MySQL 配置或其他东西?我不相信在 MySQL 中没有解决方案可以在没有死锁的情况下进行同步更新。