在原子数据库事务中与外界通信

时间:2014-11-07 14:23:27

标签: python mysql django transactions atomicity

我正在实现一个导入工具(Django 1.6),它可以获取一个可能非常大的CSV文件,验证它并根据用户确认导入或不导入。鉴于潜在的大型文件大小,文件的处理是通过flowy(亚马逊的SWF上的python包装器)完成的。每个导入作业都保存在数据库和工作流的表中,这非常简单,只包含一个活动,基本上调用一个运行导入的方法,并在作业记录中保存有关文件处理的所有必要信息。数据库。

棘手的是:我们现在必须使这个导入原子。要么保存所有记录要么保存所有记录。但是导入表中保存的一个东西是导入的进度,它是根据文件阅读器的位置计算的:

progress = (raw_data.tell() * 100.0) / filesize

此进度由客户端的AJAX进度条小部件使用。因此,只需将@transaction.atomic添加到循环文件并导入行的方法不是解决方案,因为进度只会在提交时保存。

CSV文件只包含一种类型的记录并影响单个表。如果我能以某种方式只在这个表上做一个事务,让我可以免费更新进度列,这将是理想的选择。但是从我到目前为止发现的情况看来似乎是不可能的。到目前为止,我能想到的唯一解决方案是每次需要更新进度时在其中打开一个新线程和一个新的数据库连接。但我一直在想......这甚至会起作用吗?是不是有一个更简单的解决方案?

1 个答案:

答案 0 :(得分:0)

一种简单的方法是使用READ UNCOMMITTED事务隔离级别。 可以允许脏读,这将允许您的其他进程看到进度,即使事务尚未提交。但是,这是否有效将取决于数据库。 (我不熟悉MySQL,但这在PostgreSQL中不起作用,因为READ UNCOMMITTEDREAD COMMITTED的工作方式相同。)

关于您提出的解决方案,您不一定需要新线程,您只需要与数据库建立新的连接。在Django中实现这一点的一种方法可能是利用multiple database support。我想象这样的事情:

  1. 如文档中所述,使用不同的名称向DATABASES添加新条目,但设置与default相同。从Django的角度来看,我们正在使用多个数据库,即使我们实际上只想获得到同一数据库的多个连接。

  2. 如果有时间更新进度,请执行以下操作:

    JobData.objects.using('second_db').filter(id=5).update(progress=0.5)
    

    这应该在自己的自动提交事务中进行,允许您的Web服务器看到进度。

  3. 现在,这有用吗?老实说我不知道​​,我从来没有尝试过类似的东西!