我有一个充满行和多个线程的数据库,这些线程正在访问这些行,在一个函数中输入其中的一些数据,产生一个输出,然后用输出填充该行缺失的列。
这里是问题所在:每一行都有一个 unprocessed
标志,默认情况下为 true。所以每个线程都在寻找带有这个标志的行。但是每个线程都得到相同的行,事实证明...因为该行在线程的作业完成后被标记为已处理,这可能会在几秒钟后发生。
我避免这种情况的一种方法是为每一行插入一个 currently_processed
标志,将其标记为 false,一旦线程访问该行,将其更改为 true。然后当线程完成时,只需将 if 更改回 false。这个问题是我必须使用某种锁定,并且在这种情况发生之前不允许任何其他线程做任何事情。我想知道是否有一种替代方法,我不必进行线程锁定(通过互斥体或其他东西)从而减慢整个过程。
如果有帮助,代码是用 Ruby 编写的,但这个问题与语言无关,但这里是演示我正在使用的线程类型的代码。所以没什么特别的,就像几乎所有语言一样,在最低级别上进行线程化:
3.times do
Thread.new do
row = get_database_row
result = do_some_processing(row)
insert_results_into_row(result)
end
end.each(&:join)
最佳答案
此处“真正”的答案是您需要一个数据库事务。当一个线程获取该行时,数据库 需要知道该行当前正在等待处理。
您不能在您的应用程序中解决这个问题!你看,当两个线程同时查看同一行时,它们可以都尝试写入该标志……是的,它肯定会更改为“当前处理”;然后两个线程都将更新行数据并将其写回。如果任何处理导致相同的最终结果,那么这可能不是问题;但如果不这样做,就会出现各种数据完整性问题。
所以真正的答案是你退后一步,看看你的特定数据库是如何设计的,以便处理这些事情。
关于ruby - 如何处理 'lock' 数据库行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41691821/