簡體   English   中英

Django:如何在事務中包裝批量更新/插入操作?

[英]Django: how to wrap a bulk update/insert operation in transaction?

這是我的用例:

  • 我有多個並行運行的芹菜任務
  • 每個任務可以批量創建更新許多對象。 為此,我正在使用django-bulk

所以基本上我使用的是一個非常方便的功能insert_or_update_many

  1. 它首先執行選擇
  2. 如果找到對象,則更新它們
  3. 否則會創建它們

但這引入了並發問題。 例如:如果在步驟1中不存在對象,則將其添加到要插入的對象列表中。 但是在此期間可能發生了另一個Celery任務創建了該對象,並且當它嘗試執行批量插入時(步驟3),我收到重復Entry的錯誤。

我想我需要將這3個步驟包裝在“阻止”塊中。 我已經閱讀了有關事務的內容,並嘗試with transaction.commit_on_success:塊將步驟1,2,3包裝到with transaction.commit_on_success:

with transaction.commit_on_success():
    cursor.execute(sql, parameters)
    existing = set(cursor.fetchall())
    if not skip_update:
        # Find the objects that need to be updated
        update_objects = [o for (o, k) in object_keys if k in existing]
        _update_many(model, update_objects, keys=keys, using=using)
    # Find the objects that need to be inserted.
    insert_objects = [o for (o, k) in object_keys if k not in existing]
    # Filter out any duplicates in the insertion
    filtered_objects = _filter_objects(con, insert_objects, key_fields)
    _insert_many(model, filtered_objects, using=using)

但這對我不起作用。 我不確定我是否對交易有充分的了解。 我基本上需要一個塊,可以在其中放置幾個​​操作,以確保沒有其他進程或線程正在訪問(寫入)我的數據庫資源。

我基本上需要一個塊,可以在其中放置幾個​​操作,以確保沒有其他進程或線程正在訪問(寫入)我的數據庫資源。

Django交易通常不會為您保證。 如果您來自計算機科學的其他領域,那么您自然會以這種方式將事務視為阻塞,但是在數據庫世界中,鎖的級別不同, 隔離級別也不同,並且每個數據庫的鎖也不同。 因此,要確保您的事務能夠做到這一點,您將必須了解事務,鎖及其性能特征,以及數據庫提供的用於控制它們的機制。

但是,讓一堆進程都試圖鎖定表以執行競爭插入並不是一個好主意。 如果很少發生沖突,則可以執行某種形式的樂觀鎖定,如果失敗則重試事務。 或者,您可以將所有這些celery任務定向到一個進程中(如果您無論如何都要獲取表鎖,則並行執行此操作都沒有性能優勢)。

我的建議是從忘記批量操作開始,並使用Django的update_or_create一次只執行一行。 只要您的數據庫具有防止重復條目的約束(聽起來確實如此),那么它就不會出現上述競爭條件。 如果性能確實不可接受,那么可以考慮使用更復雜的選項。

采用開放式並發方法意味着您不必像通過獲取表鎖那樣防止沖突,而是可以正常進行,然后在發現問題時重試該操作。 在您的情況下,它可能類似於:

while True:
    try:
        with transaction.atomic():
            # do your bulk insert / update operation
    except IntegrityError:
        pass
    else:
        break

因此,如果遇到競爭狀況,則產生的IntegrityError將導致transaction.atomic()塊回滾已進行的所有更改, while循環將強制重試該事務(現在大容量操作現在可能會進行重試)查看新存在的行,並將其標記為要更新而不是插入)。

如果沖突很少發生,則這種方法非常有效,如果沖突頻繁發生,則非常糟糕。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM