flaskd的sqlalchemy的高级用法,最全面的sqlalchemy关键常用知识点总结
sqlalchemy的exist用法
判断是否存在
1 | from sqlalchemy.sql import exists |
sqlalchemy的func用法
from sqlalchemy.sql import func
• func.count:统计行的数量。
• func.avg:求平均值。
• func.max:求最大值。
• func.min:求最小值。
• func.sum:求和。
group_by 分组查询和过滤
session.query(User.gender,func.count(User.id)).group_by(User.gender).all()
result = session.query(User.age,func.count(User.id)).group_by(User.age).having(User.age >= 18).all()
group_by 使用的是having 使用filter是不可以的
sqlalchemy使用 sql语句
1 | stmt = text("SELECT name, id, fullname, nickname " |
1 | from sqlalchemy import text |
from_statement+text+params 可以使用原生sql语句进行查询
subquery子查询
1 | stmt = session.query(User.city.label("city"),User.age.label("age")).filter(User.username=='李A').subquery() |
子查询可以让多个查询变成一个查询,只要查找一次数据库,性能相对来讲更加高效一点。不用写多个sql语句就可以实现一些复杂的查询。那么在sqlalchemy中,要实现一个子查询,应该使用以下几个步骤:
sqlalchemy的label用法
用于subquery子查询或者是对单字段的查询
MySQL的事务隔离级别
Serializable 串行化,一个事务一个事务的执行
Repeatable read 可重复读,无论其他事务是否修改并提交了数据,在这个事务中看到的数据值始终不受其他事务影响
Read committed 读取已提交,其他事务提交了对数据的修改后,本事务就能读取到修改后的数据值
Read uncommitted 读取为提交,其他事务只要修改了数据,即使未提交,本事务也能看到修改后的数据值。
MySQL数据库默认使用可重复读( Repeatable read),而使用乐观锁的时候,如果一个事务修改了库存并提交了事务,那其他的事务应该可以读取到修改后的数据值,所以不能使用可重复读的隔离级别,应该修改为读取已提交Read committed。
乐观锁
乐观锁并不是真实存在的锁,而是在更新的时候判断此时的库存是否是之前查询出的库存,如果相同,表示没人修改,可以更新库存,否则表示别人抢过资源,不再执行库存更新。类似如下操作
来自 https://blog.csdn.net/hello_mumu/article/details/82253456
rom django.http import HttpResponse
from rest_framework.generics import GenericAPIView
from app01.models import GoodsInfo
class Goods(GenericAPIView):
“”” 购买商品 “””
def post(self, request):
# 获取请求头中查询字符串数据
goods_id = request.GET.get('goods_id')
count = int(request.GET.get('count'))
while True:
# 查询商品对象
goods = GoodsInfo.objects.filter(id=goods_id).first()
# 获取原始库存
origin_stock = goods.stock
# 判断商品库存是否充足
if origin_stock < count:
return HttpResponse(content="商品库存不足", status=400)
# 演示并发请求
import time
time.sleep(5)
# 减少商品的库存数量,保存到数据库
# goods.stock = origin_stock - count
# goods.save()
""" 使用乐观锁进行处理,一步完成数据库的查询和更新 """
# update返回受影响的行数
result = GoodsInfo.objects.filter(id=goods.id, stock=origin_stock).update(stock=origin_stock - count)
if result == 0:
# 表示更新失败,有人抢先购买了商品,重新获取库存信息,判断库存
continue
# 表示购买成功,退出 while 循环
break
return HttpResponse(content="操作成功", status=200)
sqlalchemy悲观锁 with_for_update
业务中有个需求,就是可能会遇到并发读取某一行数据,然后修改这行数据,这时候就涉及到并发的锁了
比如:
address表有个user_id=3的字段的status如果为0则要update,为1则不需要,如果没有锁,当两个session同时访问到user_id为3的字段时,此时status都为0,那么两个session都会对数据库做一次update,这等于update了两次,那么怎么避免这种情况呢?就要用到with_for_update()方法了:
下面是session1的代码
session1:
addr = Address.query.filter_by(user_id=3).with_for_update().first
if addr.status == 0:
addr.status = 1
db.session.commit()
下面是session2的代码:
session2:
addr = Address.query.filter_by(user_id=3).with_for_update().first
if addr.status == 0:
addr.status = 1
db.session.commit()
那么当session1抢先拿到锁的时候,在执行到最后的commit之前,session2都会卡住,当session1释放锁,session2拿到锁之后,status已经改为1了.