如何在 Django 中执行 table/row 锁

How to perform table/row locks in Django

在 Django 在 Apache 上 运行 或具有多个 Gunicorn worker 的生产环境中,它存在并发问题的风险。

因此,我很惊讶地发现 Django 的 ORM 没有明确支持 table/row 锁定。它非常方便地支持事务,但这只解决了一半的并发问题。

使用 MySQL 后端,在 Django 中执行锁定的正确方法是什么?还是 Django 的框架中有其他东西在起作用,使它们变得不必要?

Django 没有明确提供 API 来执行 table 锁定。根据我的经验,设计良好的代码很少需要锁定整个 table,大多数并发问题都可以通过行级锁定来解决。这是最后的努力:它没有解决并发问题,它只是扼杀了任何并发尝试。

如果您确实需要 table 级锁定,您可以使用游标并执行原始 SQL 语句:

from django.db import connection

with connection.cursor() as cursor:
    cursor.execute("LOCK TABLES %s READ", [tablename])
    try:
        ...
    finally:
        cursor.execute("UNLOCK TABLES;")

考虑将事务隔离级别设置为可序列化,并使用 MySQL table 支持事务的类型(MyISAM 不支持,InnoDB 支持。)

确保您有一个支持事务的后端后,您需要禁用自动提交 (https://docs.djangoproject.com/en/1.8/topics/db/transactions/#autocommit-details),然后确保您的代码在您考虑的内容结束时发出适当的提交或回滚语句待交易。

上面引用的文档中有一两个例子..

这样做需要更多的工作和考虑,但会为您提供交易。