django框架(十三):ORM中的锁与事务

文章目录

    • 一、锁(了解)
    • 二、事务
        • 1、全局开启(不推荐)
        • 2、局部使用事务(推荐)
            • (1)给函数做装饰器来使用
            • (2)作为上下文管理器来使用,其实就是设置事务的保存点

看本篇博文之前需要对mysql锁与事务非常熟悉,
点我学习:mysql锁机制
点我学习:mysql事务

一、锁(了解)

行级锁

select_for_update(nowait=False, skip_locked=False) #注意必须用在事务里面,至于如何开启事务,我们看下面的事务一节。

返回一个锁住行直到事务结束的查询集,如果数据库支持,它将生成一个 SELECT … FOR UPDATE 语句。

举个例子:

entries = Entry.objects.select_for_update().filter(author=request.user)  #加互斥锁,由于mysql在查询时自动加的是共享锁,所以我们可以手动加上互斥锁。create、update、delete操作时,mysql自动加行级互斥锁

所有匹配的行将被锁定,直到事务结束。这意味着可以通过锁防止数据被其它事务修改。

一般情况下如果其他事务锁定了相关行,那么本查询将被阻塞,直到锁被释放。 如果这不想要使查询阻塞的话,使用select_for_update(nowait=True)。 如果其它事务持有冲突的锁,互斥锁, 那么查询将引发 DatabaseError 异常。你也可以使用select_for_update(skip_locked=True)忽略锁定的行。 nowait和  skip_locked是互斥的,同时设置会导致ValueError。

目前,postgresql,oracle和mysql数据库后端支持select_for_update()。 但是,MySQL不支持nowait和skip_locked参数。

使用不支持这些选项的数据库后端(如MySQL)将nowait=True或skip_locked=True转换为select_for_update()将导致抛出DatabaseError异常,这可以防止代码意外终止。

二、事务

关于MySQL的事务处理,我上面的mysql博客已经说的很清楚了,那么我们来看看Django是如果做事务处理的。django1.8版本之前是有很多种添加事务的方式的,中间件的形式(全局的)、函数装饰器的形式,上下文管理器的形式等,但是很多方法都在1.8版之后给更新了,下面我们只说最新的三种方式:

1、全局开启(不推荐)

在Web应用中,常用的事务处理方式是将每个请求都包裹在一个事务中。这个功能使用起来非常简单,你只需要将它的配置项ATOMIC_REQUESTS设置为True。

它是这样工作的:当有请求过来时,Django会在调用视图方法前开启一个事务。如果请求却正确处理并正确返回了结果,Django就会提交该事务。否则,Django会回滚该事务。

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'mxshop',
        'HOST': '127.0.0.1',
        'PORT': '3306',
        'USER': 'root',
        'PASSWORD': '123',
        'OPTIONS': {
            "init_command": "SET default_storage_engine='INNODB'",
       #'init_command': "SET sql_mode='STRICT_TRANS_TABLES'", #配置开启严格sql模式


        }
        "ATOMIC_REQUESTS": True, #全局开启事务,绑定的是http请求响应整个过程
        "AUTOCOMMIT":False, #全局取消自动提交,慎用
    },
  'other':{
    'ENGINE': 'django.db.backends.mysql', 
            ......
  } #还可以配置其他数据库
}

上面这种方式是统一个http请求对应的所有sql都放在一个事务中执行(要么这个http请求成功,要么这个http请求失败,对数据库不产生任何影响)。

2、局部使用事务(推荐)

(1)给函数做装饰器来使用
from django.db import transaction

@transaction.atomic
def viewfunc(request):
    # This code executes inside a transaction.
    do_stuff()

整个视图函数为一个事务!

(2)作为上下文管理器来使用,其实就是设置事务的保存点
from django.db import transaction

def viewfunc(request):
    with transaction.atomic():   # 保存点
        # This code executes inside a transaction.
        do_more_stuff()

with transaction.atomic()下的缩进部分为一个事务!

你可能感兴趣的:(#,框架,django)