python - Django 中的游标是否在打开的事务中运行?

标签 python sql django postgresql python-db-api

我的 Django 应用程序正在使用一些自定义 SQL,我正在这样的 View 中执行这些 SQL:

db = router.db_for_write(model)
cursor = connections[db].cursor()
cursor.execute("INSERT INTO ....")

由于我使用的是 TransactionMiddleware,所以我的 View 在一个事务中运行,但我不清楚获取这样的新游标是否会“转义”当前打开的事务,或者游标是否是仍然是公开交易的一部分。我收到一些错误消息,使我相信游标正在事务内部运行。

我希望能够使用游标在 TransactionMiddleware 打开的事务之外执行 SQL 命令。这可能吗?

如果重要的话,我正在运行带有 PostgreSQL 8.4 数据库的 Django 1.4。

最佳答案

我相信您需要一个单独的数据库连接来获得一个单独的同步事务。我也很确定 django 每个数据库只管理一个连接。但是你可以创建另一个。可能有一些很好的理由不这样做。复杂性浮现在脑海中。

我认为这样的事情会起作用:

from django.conf import settings
from django.db.utils import ConnectionHandler

def my_view(request):
    """Flirt with complexity by using two connections to db"""
    private_connections = ConnectionHandler(settings.DATABASES)
    db = router.db_for_write(model)
    new_conn = private_connections[db]
    new_conn.enter_transaction_management()
    new_conn.managed(True)
    new_cur = new_conn.cursor()
    new_cur.execute("INSERT INTO ...")
    new_conn.commit()
    new_conn.close()

请注意,您不能使用 django.db.transaction因为它在 django.db.connections 中的全局连接实例上运行,但无论如何,这只是连接对象上事务管理方法的薄包装。

我想真正的问题是为什么要这样做?! Lakshman Prasad 的回答有什么问题?您可以随时提交/回滚,因此没有什么可以阻止您在单个 View 中的不同事务中执行不同的任务。事务必须是并行的而不是连续的这一事实暗示它们之间存在某种逻辑联系,在我看来这表明它们确实应该在同一个事务中。

另一方面,如果您只是想模拟某种离线处理,其成功或失败与 View 完全无关,请考虑设置消息队列并执行这些插入在一个单独的过程中。 Celery是一个流行的包来做这件事。但是,如果响应时间不是主要问题,我仍然认为连续事务就足够了。

更新:

如果您希望数据库支持的缓存在自动提交模式下运行,同时仍然在单个(单独的)事务中运行您的业务逻辑,可以使用 django 方法。您需要做的就是确保缓存发生在 commit_on_success外部 :

  • 如果您只是使用缓存中间件,请确保它在 TransactionMiddleware 之外.

  • 如果您使用缓存 View 装饰器,我敢猜测您可以禁用 TransactionMiddleware (或将问题 View 放在 autocommit 装饰器中)并使用 commit_on_success缓存装饰器内部装饰器。看起来很有趣,但我不知道为什么它不起作用:

    @transaction.autocommit
    @cache_page(500)
    @transaction.commit_on_success
    def my_view(request):
        "..."
    
  • 如果您使用模板缓存或进行更多涉及手动缓存,您也可以禁用 TransactionMiddleware (或将问题 View 放在 autocommit 装饰器中)并使用 commit_on_success作为上下文管理器,仅将您需要的代码放入托管事务中,将 View 的其余部分留在自动提交中。

    @transaction.autocommit
    def my_view(request):
        data = cache.get(some_key)
        with transaction.commit_on_success():
            context = do_some_processing(data)
        cache.set(some_key, context['data'])
        return render('template/with/cache/blocks.html', context=context)
    

关于python - Django 中的游标是否在打开的事务中运行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11554844/

相关文章:

用于 linux 终端 shell 的 Python 3.3

django - 在 Django 模型中限制一条记录为默认值

python - Django 通用关系不起作用

python - Django Haystack SOLR 中的排序顺序

java - 在 O(n) 时间内找到正确的路径

python - heroku 不支持 django 应用程序并引发错误

python - 在 GUI 中显示函数

mysql - 这些 MySQL SELECT 查询是否代表不同的内部连接?

mysql - 根据最近的日期关联两个表

java - 使用 SQL Server 方言将 Hibernate 配置为转义 LIKE 子句中的下划线