从多个进程和线程读取和写入SQL数据库

时间:2020-04-25 09:37:20

标签: python mysql multithreading sqlalchemy multiprocessing

我构建了一个应用程序,该应用程序从多个城市的API连续获取天气数据,并使用Python中的多个进程和线程将数据读取/写入SQL(MySQL)数据库。我在这个方面比较陌生。

假设有两个过程。每个进程产生N个线程,每个城市一个线程。每个线程针对不同的城市执行相同的逻辑。

进程1中的线程1每60秒从纽约的API提取数据并将其写入SQL表X。进程2中的线程2每60秒从Los Angeles获取数据并将其写入SQL Table X。

表X具有以下属性:Record Index (Int), City (Varchar), Processed (Boolean), Some Data (Int)。当进程1中的线程将数据写入表X时,默认情况下Processed属性被标记为False

移动到进程2 ...进程2中的线程1每60秒从表X中获取纽约的未处理数据(所有记录Processed=False),并将其复制到表Y,并将此数据标记为已处理表2中的线程2每60秒从Los Angeles的表X中获取未处理的数据,将其复制到表Y中,并将该数据标记为表X中已处理。

我使用SQLAlchemy读取和写入数据库。我通过以下方法在每个进程中初始化一个新引擎:

engine = create_engine(f'mysql+pymysql://{user}:{password}@{host}/{database}')

我通过以下方式执行SQL语句:

with engine.begin() as connection:
     connection.execute(sql_statement)

我遇到的问题是,我需要阻止流程1向纽约的表X添加新数据(例如),直到流程2完成1.)将纽约的未处理数据复制到表Y和2)标记。复制的数据在表X中为“已处理= True”。否则,可以将新数据添加到进程1中的表X并在进程2中标记为已处理,而无需实际复制到表Y中。

我相信我可以使用锁(multiprocessing.Lock())解决此问题,但是除了阻止线程在所有进程中处理New York之外,它还将阻止线程处理Los Angeles(以及其他任何要处理的城市)这个问题)。

我可以切换架构,以便每个进程负责处理不同的城市,并且每个线程运行不同的逻辑(数据获取,数据处理)。从本质上讲,这将与现在相反。但是,我需要做的很多处理都是CPU限制的,所以我认为这样做的效率可能会降低。

使用多处理锁是解决此问题的最佳方法吗?还有什么其他选择?

1 个答案:

答案 0 :(得分:1)

我想不多的东西,只是想给您一些想法

  1. 文件锁(在已知位置,其名称可以从您正在操作的上下文派生)。有一些库为您提供文件锁定原语(文件锁定)
  2. 以所需的粒度级别在DB中实现锁定原语。原语可以是整数。这两个过程都必须对此进行同步。都可能同时读取该原语,对其进行递增并尝试将其写回,但是只有一个会成功写入-您必须处理此问题

我有一个qn:您提到您正在执行CPU绑定任务。在这种情况下,线程模型在每个流程中的效率如何?