在Django中,如何实现一个事务的可重复读?

In Django, how to achieve repeatable reads for a transaction?

我有一个函数,它对同一个数据集执行多个查询,我想确保所有查询都会看到完全相同的数据。

就SQL而言,这意味着支持它的数据库的可重复读取隔离级别。如果数据库不可用,我不介意更高级别甚至完全锁定。

据我所知,情况并非如此。 IE。如果我 运行 像这样的代码在一个 Python shell:

with transaction.atomic():
    for t in range(0, 60):
        print("{0}: {1}".format(t, MyModel.objects.count()))
        time.sleep(1)

一旦我在另一个中执行 MyModel.objects.create(...),运行ning 循环看到的值立即增加。这正是我想要避免的。进一步的测试显示行为符合 READ COMMITTED 级别,这对我的口味来说太宽松了。

我还想强调一点,我只希望对单个功能使用更严格的隔离级别,而不是对整个项目。

我最好的选择是什么?

在我的特殊情况下,我唯一关心的数据库是 PostgreSQL 9.3+,但我也希望与 SQLite3 兼容,在这种情况下,即使完全锁定整个数据库也可以与我一起。然而,显然,解决方案越通用,它就越受欢迎。

你是对的,postgres 中的默认事务隔离级别是 READ COMMITTED。 您可以在设置中轻松更改它以测试它是否符合您的需求: https://docs.djangoproject.com/en/1.8/ref/databases/#isolation-level

此外,我怀疑您会遇到一些性能问题,因为 postgres 在处理事务时运行非常高效。即使在 SERIALIZABLE 模式下。此外 mysql 具有可重复读取的默认隔离级别,正如我们所见,它也不会影响性能。

无论如何,您可以在需要时手动设置隔离模式,如下所示: http://initd.org/psycopg/docs/extensions.html#isolation-level-constants

要设置自定义事务隔离级别,您可以尝试以下操作:

from django.db import connection

with transaction.atomic():
    cursor = connection.cursor()
    cursor.execute('SET TRANSACTION ISOLATION LEVEL REPEATABLE READ')
    # logic

此外,我建议您先在设置中更改默认模式(如果可以的话)。 然后,如果适合您的需要,您可以将其删除并在特殊位置修改代码。