Sql server Perl SQL和文件创建竞争条件

Sql server Perl SQL和文件创建竞争条件,sql-server,perl,race-condition,Sql Server,Perl,Race Condition,如何处理计划每分钟运行的脚本实例之间的竞争条件,为目录中的每个文件执行以下任务: 连接到SQL数据库并检查表中的最后一个元素文件名 使用下一个可用文件名在多个文件夹中创建多个文件 使用文件名和已创建文件的信息插入SQL新记录 因为该过程每1分钟运行一次,所以可能有2个实例重叠并在同一文件上工作。我可以通过文件锁定和跳过已打开的文件来防止这种情况,但问题仍然存在: 正在检查数据库2中的下一个可用文件名进程希望使用相同的文件名 使用此文件名创建文件 进程A获取inputA.jpg并找到下一个可用文件

如何处理计划每分钟运行的脚本实例之间的竞争条件,为目录中的每个文件执行以下任务:

连接到SQL数据库并检查表中的最后一个元素文件名 使用下一个可用文件名在多个文件夹中创建多个文件 使用文件名和已创建文件的信息插入SQL新记录 因为该过程每1分钟运行一次,所以可能有2个实例重叠并在同一文件上工作。我可以通过文件锁定和跳过已打开的文件来防止这种情况,但问题仍然存在:

正在检查数据库2中的下一个可用文件名进程希望使用相同的文件名 使用此文件名创建文件 进程A获取inputA.jpg并找到下一个可用文件名image\u 01

进程B获取inputB.jpg并找到下一个可用文件名image\u 01

于是混乱开始了

不幸的是,我无法在SQL表中插入任何占位符记录以显示正在处理下一个文件名

循环的伪代码:

实际的代码要复杂一些,包括文件修改和对2个SQL表的事务性插入。如果createFile失败,应用程序将回滚以前创建的所有文件。当应用程序的一个实例正在创建文件abc,而第二个实例出现文件abc已经存在的错误时,显然会产生问题

编辑:


当然,将脚本限制为只有一个实例可能是解决方案,但我希望找到一种并行运行它们的方法。如果没有办法,我们可以将其作为副本关闭。

您需要将从数据库返回下一个可用文件名的代码设置为数据库中的原子代码,以便数据库不能两次返回相同的文件名。这实际上是一个数据库问题,而不是perl问题本身

您不会说您正在使用哪个数据库,但有几种方法可以做到这一点。 在MySQL中,一种幼稚而粗野的方法是,perl脚本在计算新表并执行其工作时,使用文件名对表执行锁表写入。使用新文件名更新表后,可以释放锁。然而,表锁不能很好地处理事务

或者您可以做一些更优雅的事情,比如在数据库本身中实现一个具有适当锁定的存储过程,以返回新的文件名

或者使用自动增量列,以便每次向表中添加内容时,都会得到一个新的数字,从而得到一个新的文件名

但这一切都会变得相当复杂;如果同时有多个事务,数据库如何解析这些事务通常是可配置的,因此我无法告诉您将发生什么


考虑到您的代码听起来似乎主要是在重新组织磁盘上的数据,同时运行多个作业没有多大好处;无论如何,这段代码可能是I/O绑定的。在这种情况下,只需修改代码就简单多了,其他人建议一次只运行一个副本。

@Саа27这实际上是一个非常简单的解决方案。我的目标是,如果第一个实例需要超过60秒的时间,就不会阻止第二个实例启动,但这可能足够了。谢谢。可以随时聚集一个锁文件,并比较MTIME。可能重复的
foreach ($file)
{
   $name = findFileNameInSql($file)
   $path1 = createFile($name, $settings1);
   $path2 = createFile($name, $settings2);
   $path3 = createFile($name, $settings3);
   addToSql($file, $name, $path1, $path2, $path3)
}