Массовое обновление в django с пакетным обновлением в нескольких транзакциях

У меня есть определенный код, который обновляет большое количество строк:

from simple_history.utils import bulk_update_with_history
from django.utils.timezone import now

bulk_update_list = []
for chart in updated_chart_records:
    chart.coder_assignment_sequence = count
    chart.queue_id = work_queue_pk
    chart.level_id = role_id
updated_num = bulk_update_with_history(bulk_update_list, Chart, ["coder_assignment_sequence", "l1_auditor_assignment_sequence", "l2_auditor_assignment_sequence", "l3_auditor_assignment_sequence","queue_id", "level_id", "comments", "reason_id"],
                                                           batch_size=10000, default_change_reason="work_queue")

Теперь data здесь может быть очень много, иногда тысячи строк для обновления.

Это привело к тому, что база данных находилась в lock:relation состоянии около 2-3 минут.

При препарировании метода bulk_update_with_history, принадлежащего пакету simple-history, в строке doc указано, что:

def bulk_update_with_history(
    objs,
    model,
    fields,
    batch_size=None,
    default_user=None,
    default_change_reason=None,
    default_date=None,
    manager=None,
):
    """
    Bulk update the objects specified by objs while also bulk creating
    their history (all in one transaction).
    :param objs: List of objs of type model to be updated
    :param model: Model class that should be updated
    :param fields: The fields that are updated
    :param batch_size: Number of objects that should be updated in each batch

Теория заключается в том, что эта конкретная функция упаковывает все пакетные обновления в одну транзакцию, что и привело к блокировке состояния БД.

Я хочу знать, как batch_size работает в bulk_update. В Django doc говорится, что:

The batch_size parameter controls how many objects are saved in a single query. The default is to update all objects in one batch.

Также было предложено разбить на куски список обновляемых записей и вызывать bulk_update_with_history для каждого куска. Это обеспечит отдельную транзакцию для каждого куска и тем самым снимет блокировку.

Есть какие-нибудь предложения или идеи по этому поводу?

Вернуться на верх