You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django/PostgreSQL事务隔离级别设置失效问题求助

解决Django+PostgreSQL设置Serializable事务隔离级别的问题

我看到你尝试把事务隔离级别设为最严格的Serializable,但配置后始终停留在Read Committed,并发测试也没达到预期效果。咱们一步步拆解问题并解决:

核心问题分析

你的配置存在两个关键错误:

  1. OPTIONS位置错误:你把OPTIONS和default数据库配置平级放置,但Django要求OPTIONS必须嵌套在具体的数据库(比如default)配置内部,导致原有配置完全没被读取。
  2. Heroku配置覆盖丢失:当部署到Heroku时,dj_database_url.config()会完全替换DATABASES['default']的内容,你之前设置的OPTIONS被彻底覆盖了。

修改后的正确配置

把OPTIONS放到default配置内部,并且在Heroku生成配置后重新注入隔离级别设置:

import psycopg2.extensions
import os
from django.conf import settings

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(settings.BASE_DIR, 'db.sqlite3'),
        # 将OPTIONS嵌套进default配置内
        'OPTIONS': {
            'isolation_level': psycopg2.extensions.ISOLATION_LEVEL_SERIALIZABLE,
        }
    }
}

if on_heroku:
    # 先获取Heroku的数据库配置
    DATABASES['default'] = dj_database_url.config()
    # 为Heroku配置添加隔离级别OPTIONS
    DATABASES['default']['OPTIONS'] = {
        'isolation_level': psycopg2.extensions.ISOLATION_LEVEL_SERIALIZABLE,
    }

正确验证隔离级别

你当前查询的default_transaction_isolation是数据库全局默认值,不是当前事务的实际隔离级别。应该查询当前连接/事务的级别:

@require_http_methods(["POST"])
@transaction.atomic
@login_required()
def api_test_add_one(request):
    cursor = connection.cursor()
    # 查询当前事务的实际隔离级别
    cursor.execute('SHOW transaction_isolation')
    logger.info("当前事务隔离级别: " + str(cursor.fetchone()))
    
    # 也可以直接通过Django连接对象获取
    logger.info("Django连接隔离级别: " + str(connection.isolation_level))
    return HttpResponse("{}", content_type="application/json")

并发测试的注意事项

Serializable级别会通过检测事务间的写冲突来阻止幻读,当冲突发生时PostgreSQL会自动回滚其中一个事务并抛出TransactionRollbackError。Django的@transaction.atomic默认会自动重试事务(最多5次),你可以观察日志中的重试记录,或者在代码中捕获该异常做自定义处理。

内容的提问来源于stack exchange,提问作者Patrik Beck

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 08:18:03