嘿,我使用delayed_job进行后台处理。我的服务器有8个CPU,使用MySQL,并启动了7个delayed_job进程。
RAILS_ENV=production script/delayed_job -n 7 start
Q1: 我想知道是否可能有两个或更多的delayed_job进程开始处理相同的进程(数据库中的相同记录行)。我查看了delayed_job插件的代码,但无法找到锁定指令(没有锁表或SELECT...FOR UPDATE)。
我认为每个进程在执行对locked_by列的UPDATE之前都应该锁定数据库表。它们通过更新locked_by字段(UPDATE delayed_jobs SET locked_by...)来简单地锁定记录。这样就足够了吗?不需要锁定吗?为什么?我知道UPDATE的优先级高于SELECT,但我认为在这种情况下没有这种影响。
我对多线程情况的理解是:
Process1: Get waiting job X. [OK]
Process2: Get waiting jobs X. [OK]
Process1: Update locked_by field. [OK]
Process2: Update locked_by field. [OK]
Process1: Get waiting job X. [Already processed]
Process2: Get waiting jobs X. [Already processed]
我认为在某些情况下,更多的作业可以获得相同的信息并开始处理相同的过程。
Q2: 对于一个有8个CPU的服务器而言,7个延迟作业是一个好的数量吗?为什么是/不是?
谢谢 10倍!
UPDATE jobs SET locked_at = '..', locked_by = 1 WHERE id = 12 and (locked_at is null or locked_at < '..')
,则仅在没有其他有效锁时才会更新locked_at和locked_by。DBMS首先检查where条件,然后执行更新并确保行在中间未更改。因此,您无法覆盖现有锁定。 - gregorSELECT ... FOR UPDATE
,但这并非必要且难以实现,因为所有锁定机制都不同于各种 DBMS。 - gregor[Warning] Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. The statement is unsafe because it uses a LIMIT clause. This is unsafe because the set of rows included cannot be predicted. Statement: UPDATE \
delayed_jobs` SET `delayed_jobs`.`locked_at` = '2014-10-25 02:00:25', `delayed_jobs`.`locked_by` = 'delayed_job host:www1 pid:15229' WHERE ((run_at <= '2014-10-25 02:00:25' AND (locked_at IS NULL OR locked_at < '2014-10-24 22:00:25') OR [..]` - 2called-chaos