Python 在多处理过程中,如何在异常后重置Django事务?
发生数据库异常(例如IntegrityError)后,如何重置Django事务,以便继续写入数据库 我有几个工人在自己的流程中运行,所有这些流程都是通过Python 在多处理过程中,如何在异常后重置Django事务?,python,django,python-multiprocessing,Python,Django,Python Multiprocessing,发生数据库异常(例如IntegrityError)后,如何重置Django事务,以便继续写入数据库 我有几个工人在自己的流程中运行,所有这些流程都是通过joblib包启动的,该流程数据库记录。他们都通过Django的ORM将进度写入数据库 一般来说,它们工作正常,但偶尔,如果遇到错误,例如试图用违反唯一约束的列写入记录,则会抛出IntegrityError 我有错误处理逻辑来捕获这些,记录错误,并允许它跳到下一个要处理的文件。但是,我发现一旦遇到其中一个错误,就会有效地阻止该工作者进一步访问数据
joblib
包启动的,该流程数据库记录。他们都通过Django的ORM将进度写入数据库
一般来说,它们工作正常,但偶尔,如果遇到错误,例如试图用违反唯一约束的列写入记录,则会抛出IntegrityError
我有错误处理逻辑来捕获这些,记录错误,并允许它跳到下一个要处理的文件。但是,我发现一旦遇到其中一个错误,就会有效地阻止该工作者进一步访问数据库,因为所有进一步的写入尝试都会返回臭名昭著的错误:
django.db.transaction.TransactionManagementError: An error occurred in the current transaction. You can't execute queries until the end of the 'atomic' block.
奇怪的是,我没有直接使用atomic()
,所以我假设这是Django在某处隐式运行的。我如何解决这个问题
我知道避免此错误的通常方法是显式地将写操作包装在原子中。所以我尝试了这个方法,但是,这只会导致大量死锁错误,因为使用atomic
around table编写由多个工作进程运行的代码意味着它们都是相互踩在一起的。即使我实现了错误处理代码以在死锁发生时重新运行写操作,我发现这实际上禁用了我的多处理功能。我没有让N个工作进程并行快速运行,而是让N个工作进程串行缓慢运行,因为它们都在等待彼此写入同一个表,即使99.99%的时间它们没有写入冲突行或违反任何约束
如何防止Django将所有内容包装在原子()中,以便通过事务。回滚()
手动重置事务
我用如下脚本启动我的工人:
#!/usr/bin/env python
import django
from django.db import connection
django.setup() # Fixes joblib error "A task has failed to un-serialize"
from joblib import Parallel, delayed
from tqdm import tqdm
from myapp.models import Record
def do_work(record_id):
record = Record.objects.get(id=record_id)
...do stuff and then write to Record...
records = Record.objects.filter(pending=True)
parallel_tasks = [delayed(do_work)(record.id) for record in records]
connection.close()
list(Parallel(n_jobs=cpu_count())(tqdm(parallel_tasks)))