0

DI 有一个任务表,其中包含要为不同系统完成的供应任务。每个系统都有一个独立的 Perl 进程,该进程连续运行并检查表以查看它是否有针对该给定系统的任何未完成的任务。在一个月的时间里,这个表中可能有几十万条记录。伪代码如下所示:

select oldest uncompleted task for a given provisioning system
if found a task
  update task to "in progress"
  go do some work
  update task to completed
sleep 15 seconds
repeat

试图弄清楚如何使这个过程更有效率。如果我减少睡眠时间,我会在数据库上增加额外的负载,但如果我增加睡眠时间,系统的整体响应会变得非常缓慢。理想情况下,我想完全消除睡眠,但没有额外的负载。

是否有类似于阻塞读取的 SQL 等价物?所以一个 select 语句会阻塞,直到它有东西要返回?

我曾考虑过另一个表,其中只有一个不完整的任务列表。但我仍然需要加入大桌子,所以不确定这是否真的能给我带来任何好处。

我能想出的唯一解决方案可能是在表上插入触发器,这可能会触及 /tmp 中的文件。然后 Perl 程序可以轮询那个文件的时间戳。或者也许向 Perl 程序正在通过阻塞读取侦听的命名管道发送一条小消息。

我将不胜感激有关如何解决此问题的任何帮助。这种 dB 轮询必须是一种常见的模式。

4

1 回答 1

0

一些观察。很难提供明确的答案,因为“最佳”取决于许多因素。

首先,您需要决定什么更重要 - 数据库负载或处理速度。大概是两者之间的平衡。

如果限制数据库上的活动真的很重要,那么你会想要一些集中的东西。最简单的可能是一个包含 id 和时间戳的 pending_tasks 表。一个单独的管理器进程使该表保持充值,并根据总体负载选择时间戳。当然,您需要确保该过程永远不会停止。

另一种选择是让每个处理器改变其睡眠时间。如果无事可做,就加一秒。如果有事要做,就减去一秒钟。显然,睡眠时间有一个最小值/最大值。如果你愿意,你可以更聪明地使用这些变化。

这样,每个处理器将倾向于在无事可做的情况下休息。

第三个观察 - 每个系统都有一个进程。只需获取接下来的 10 个任务(或其他)。只是在您真正开始工作之前不要将它们标记为正在进行中。

最后,您真正想要的这种异步通信在其他地方也可以使用。在 PostgreSQL 中,它们被称为通知。恐怕我不知道 MySQL 中有任何类似的功能。

高温高压

于 2013-05-01T08:24:42.760 回答