事务是有隔离级别
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
原文地址:https://www.cnblogs.com/ludingchao/p/12554513.html
时间: 2024-10-29 04:05:02