设为首页 加入收藏

TOP

08.Django基础六之ORM中的锁和事务(一)
2019-09-30 16:48:32 】 浏览:154
Tags:08.Django 基础 ORM 事务

一 锁

  行级锁

    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异常,这可以防止代码意外终止。

  表锁(了解)

class LockingManager(models.Manager):
    """ Add lock/unlock functionality to manager.

    Example::

        class Job(models.Model): #其实不用这么负载,直接在orm创建表的时候,给这个表定义一个lock和unlock方法,借助django提供的connection模块来发送锁表的原生sql语句和解锁的原生sql语句就可以了,不用外层的这个LckingManager(model.Manager)类

            manager = LockingManager()

            counter = models.IntegerField(null=True, default=0)

            @staticmethod
            def do_atomic_update(job_id)
                ''' Updates job integer, keeping it below 5 '''
                try:
                    # Ensure only one HTTP request can do this update at once.
                    Job.objects.lock()

                    job = Job.object.get(id=job_id)
                    # If we don't lock the tables two simultanous
                    # requests might both increase the counter
                    # going over 5
                    if job.counter < 5:
                        job.counter += 1                                        
                        job.save()

                finally:
                    Job.objects.unlock()


    """    

    def lock(self):
        """ Lock table. 

        Locks the object model table so that atomic update is possible.
        Simulatenous database access request pend until the lock is unlock()'ed.

        Note: If you need to lock multiple tables, you need to do lock them
        all in one SQL clause and this function is not enough. To avoid
        dead lock, all tables must be locked in the same order.

        See http://dev.mysql.com/doc/refman/5.0/en/lock-tables.html
        """
        cursor = connection.cursor()
        table = self.model._meta.db_table
        logger.debug("Locking table %s" % table)
        cursor.execute("LOCK TABLES %s WRITE" % table)
        row = cursor.fetchone()
        return row

    def unlock(self):
        """ Unlock the table. """
        cursor = connection.cursor()
        table = self.model._meta.db_table
        cursor.execute("UNLOCK TABLES")
        row = cursor.fetchone()
        return row  

二 事务

  

  关于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': 'd
首页 上一页 1 2 3 下一页 尾页 1/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇08.Django基础六之ORM中的锁和事务 下一篇设计模式 - 七大设计原则(四)- ..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目