zoukankan      html  css  js  c++  java
  • 事务的隔离级别 另一种事务开启方式

    事务是有隔离级别

    read uncommited (读未提交):不做任何隔离,具有脏读,不可重读对,幻读的问题

    read committed (读提交):可以防止脏读,不能防止不可重复读和幻读的问题

    repeated read(可重复读):可以防止脏读,不可重复读,不能放在幻读(mysql的默认隔离级别)

    serializable(串行化):数据库运行为串行,以上问题都可以防止,但是性能低

    下面的解释都用这个user表

    脏读(a,b同时开始事务,a,b再事务,没有哪一个结束,只有两个都进入事务后,才能结束期中一个事务,两个事务都是存活的)

    1 a  开启事务  将jason的年龄改成 18岁,但是没有提交事务
    2 b  开始事务  读取jason的年龄,发现是18岁。
    
    上述的问题,
    假设a事务回滚,b事务使用的数据就是错误的,就导致程序数据不正确。

    不可重复度(a,b同时开始事务,a,b再事务,没有哪一个结束,只有两个都进入事务后,才能结束期中一个事务,两个事务都是存活的) read committed

    1 a  开始事务  将jason的年龄改成18岁,但是提交了
    2 b  开启事务  读取jason的年龄就能读取a事务修改后的jason年龄18岁。
    
    # 如果a未提交,b读取jason年龄会卡死

    可重读读(a,b同时开始事务,a,b再事务,没有哪一个结束,只有两个都进入事务后,才能结束期中一个事务,两个事务都是存活的) repeated read

    1 a  开始事务  将jason的年龄改成18岁,但是提交了
    2 b  开启事务  读取jason的年龄不能读取a事务修改后的jason年龄18岁。而是读取的是38岁

    幻读(a,b同时开始事务,a,b再事务,没有哪一个结束,只有两个都进入事务后,才能结束期中一个事务,两个事务都是存活的) serializable解决幻读问题

    #概念和不可重读有点像,不可重复度是站在修改的基础上,而幻读是站在新增的基础上
    1 a  开始事务  将所有的的年龄改成18岁
    2 b  开始事务  新增一条数据数据name=tank,age=19,而且提交了。
    3 a  重新查, 发现有一条数据 的age=19,这就是所谓的幻读。

    如何看msql的隔离级别

    select @@global.tx_isolation;    # 默认为 REPEATABLE-READ

    如何修改事务的隔离级别

    #修改配置文件     可在mysql文件夹中my.ini配置文件中查看
    transaction-isolation=Read-Committed
    #修改后一定要重启数据库    (删除后回复默认REPEATABLE-READ)

    数据库的乐观锁与悲观锁(是建立再事务的基础上)

    悲观锁

    悲观锁的概念,他觉有人会修改我读的数据。那我就再查的时候,对数据进行锁定。
    (悲观锁:假定会发送并发从图,屏蔽一切可能违反数据完整性的操作,理论上别人可以查)
    
    select age from user where id=1 for update;
    比如 上面的查出来的 age =18 
    update age改成age = age+ 1
    如果该次查询走了索引,那就是行锁,如果没有走索引就是表锁。
    
    如何释放锁呢?结束事务就释放了锁。    (commit或者rollback)
    django中的orm是如果用悲观锁?
    user.objects.select_for_update().filter(id=1).first()

    mysql使用悲观锁

    原生的sql语句:
    1 开启事务
    2 查询的时候加锁---》select * from user where id =1 for update
    3 当结束事务锁就被释放
    django中的:
    1 开始事务
    2 在查询的时候 ----》 User.objects.select_for_update().filter(id =1 ).first()
    3 可以对数据进行修改,数据永远不会被比如人修改,只有你自己能动
    4 当结束事务锁就被释放

    乐观锁

    乐观锁的本质不是锁。他是通过代码来实现锁的。他觉的别人不会修改的他的数据。他就读数据不会背别人修改。最后再修改该条数据,再where条件中添加,之前查出来的数据。以保证数据的安全性
    select age from user where id=1 ;
    比如 上面的查出来的 age =18   
    20 
    update age改成age = age+ 1  ====》19
    
    乐观锁:
    update age改成age = age+ 1 where age =18 and id =1  ====》19
    如果我发现不是18,上面的影响行数是0
    
    #如果是可重复读,上面的乐观锁无效,必须改成read committed    *django2.0以后,用乐观锁不需要修改隔离级别(应该是局部修改)*
    a update age改成age = age+ 1  ====》19 提交
    
    b select age from user where id=1; --->18     # 可重复读隔离界别下的情况,乐观锁失效
    
    update age改成age = age+ 1 where age =18 and id =1  ====》19  ---->数据已经被改

     mysql使用乐观锁(如果使用乐观锁,mysql隔离级别要变成read committed,在django2.0以后,用乐观锁不需要修改隔离级别

    乐观本质不是锁,是通过代码级别实现数据安全
    1 开始事务
    2 查询的时候不要做任何操作data= User.objects.filter(id =1 ).first()将这个条数据中的age在原来的基础上加1
    3 在修改数据的时候。User.objects.filter(id = 1 ,age = data.age).update(age = data.age+1)从而保证在我查询到我修改的这段时候,没有人动过我的数据。
    4 如果3中的更新的影响行数为1,说明数据没有被别人改动,只我动,如果3中的影响行数为0,说明该数据已经被别人修改。这时我们想要改数据,就必须重复执行2-3两不,直到3有影响行数。

    另一种事务开启方式

    django transaction用法
    from django.db import transaction
    from django.http import HttpResponse
    from django.utils.decorators import method_decorator
    
    
    # 类中添加装饰器,保证在该类中所有的数据库操作都在一个事物中
    @method_decorator(transaction.atomic, name='dispatch')
    class MyView1(object):
        
        def get(self, request):
            return HttpResponse('GET')
        
        def post(self, request):
            return HttpResponse('POST')
    
    
    class MyView2(object):
        
        # 保证在该函数中所有的数据库操作都在一个事物中
        @transaction.atomic
        def post(self, request):
    
            # 设置事物保存点(可设多个)
            t1 = transaction.savepoint()
    
            # 如果有异常情况可回滚到指定的保存点
            transaction.savepoint_rollback(t1)
    
            # 如果没有异常可提交事物
            transaction.savepoint_commit(t1)
            return HttpResponse('POST')

    回滚点可以参考

    https://blog.csdn.net/rockpk008/article/details/25437415

  • 相关阅读:
    php遇到Allowed memory size of 134217728 bytes exhausted问题解决方法
    sql语句 两表关联查询计算数量
    mui 关键词查询
    fatal error C1189: #error : Building MFC application with /MD[d] (CRT dll version) requires MFC sha
    mui mui-control-item获得选中的标签
    mui横向滑动菜单
    淘宝客类别id大全
    (大数据工程师学习路径)第二步 Vim编辑器----高级功能入门
    (大数据工程师学习路径)第二步 Vim编辑器----查找替换
    (大数据工程师学习路径)第二步 Vim编辑器----Vim文档编辑
  • 原文地址:https://www.cnblogs.com/ludingchao/p/12554513.html
Copyright © 2011-2022 走看看