django中的model.update方法是否在保存实例之前将表锁定?

发布于 2025-01-21 04:48:02 字数 401 浏览 1 评论 0原文

我有一个场景,我需要将一个列的值复制到另一列中。我正在尝试

Model.objects.select_related('vcsdata').all().update(charging_status_v2=F('charging_status'))

使用F表达式以及更新来复制值会产生任何停机时间吗?它在执行操作时会锁定桌子吗?

selaction_question_for_for_more_context

I have a scenario in which I need to copy the values of one column into an another column. I am trying to do

Model.objects.select_related('vcsdata').all().update(charging_status_v2=F('charging_status'))

Does using F expression along with the update to copy the values would create any downtime? does it locks the table while performing the operation?

related_question_for_more_context

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

温柔戏命师 2025-01-28 04:48:02

简短答案:

不,它不是

Django在更新过程中唯一要做的事情(是否使用f表达式)是否保留记录的先前状态,以防万一出现问题,它可能会回滚至先前的状态。

def update(self, **kwargs):
    """
    Update all elements in the current QuerySet, setting all the given
    fields to the appropriate values.
    """
    self._not_support_combined_queries('update')
    assert not self.query.is_sliced, \
        "Cannot update a query once a slice has been taken."
    self._for_write = True
    query = self.query.chain(sql.UpdateQuery)
    query.add_update_values(kwargs)
    # Clear any annotations so that they won't be present in subqueries.
    query.annotations = {}
    with transaction.mark_for_rollback_on_error(using=self.db):
        rows = query.get_compiler(self.db).execute_sql(CURSOR)
    self._result_cache = None
    return rows

基本上在行中使用Transaction.mark_for_rollback_on_error(使用= self.db),它保留了记录的先前状态,但它不会锁定您的表格或任何类型的部分锁。

例如,如果您同时有两个同时更新(假设其中一个要比另一个更长的更长,并且一个速度较慢,一个速度更快地击中您的数据库),那么一个更快的速度将击中您的数据库较慢的一个并进行操作。然后,较慢的人将在您的表上执行其他操作( 此示例足以证明更新不会锁定您的表格 )。

另请注意,呼叫更新多个对象的更新(如果是可行的话)是我据我所知(与在每个实例或批量更新上保存的调用)的最有效方法。

Short Answer:

No, it doesn't.

The only thing Django does in update process (whether you use F expression or not) is keeping the previous state of your record(s) in case if something goes wrong it can rollback to the previous state.

def update(self, **kwargs):
    """
    Update all elements in the current QuerySet, setting all the given
    fields to the appropriate values.
    """
    self._not_support_combined_queries('update')
    assert not self.query.is_sliced, \
        "Cannot update a query once a slice has been taken."
    self._for_write = True
    query = self.query.chain(sql.UpdateQuery)
    query.add_update_values(kwargs)
    # Clear any annotations so that they won't be present in subqueries.
    query.annotations = {}
    with transaction.mark_for_rollback_on_error(using=self.db):
        rows = query.get_compiler(self.db).execute_sql(CURSOR)
    self._result_cache = None
    return rows

Basically in the line with transaction.mark_for_rollback_on_error(using=self.db), it keeps the previous state of your record, but it does not lock your table or any kind of partial locks.

For example if you have two simultaneous updates at the same time, (suppose one of them is going to take much longer than the other and also slower one hits your database before faster one) then the faster one is going to hit your database regardless of the slower one and does the operation. Then slower one is going to do some other operation on your table (this example is enough for proving that update does not lock your table).

Also note that calling update for updating multiple objects (if this is a doable thing) is the most efficient way for updating multiple objects as far as I know (comparing to calling save on each instance or bulk update).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文