最近使用到flask的sqlalchemy,因为flask对sqlalchemy做了一些封装,加上自己本身对sqlalchemy也不熟悉,用法上走了很多弯路。

因为没时间去研究sqlalchemy的源码,所以只能简单的测试下用法。

1、flask-sqlalchemy是线程安全的

  具体可以参考文章 https://blog.csdn.net/luffyser/article/details/89380186

2、每次查询完以后,记得commit,不然会占用连接池

  我在本地做了个简单的测试,如果单次查询请求完,不commit的话,连续请求几次,再发起request就没有响应了,推测是数据库连接池没释放,被占用。导致请求数据库挂起,从而导致没有response。

每次请求完,直接commit,可以解决此问题。

    def queryLast(cls):
try:
ret = db.session.query(cls).order_by(cls.version.desc()).first()
       #db.session.expunge(ret)
db.session.commit()
except:
db.session.rollback()
ret = None return ret

3、但是,如果Commit后,查询结果可能会从缓存中清掉,如果再使用查询结果的对象,还会再次建立连接查询。所以还会出现上述连接池耗尽的问题。

   从下图标黄的日志可以看出,commit后,使用返回的查询结果时,又执行了一次查询任务,并返回结果,my god!

2019-12-10 12:31:21,650 INFO sqlalchemy.engine.base.Engine BEGIN (implicit)
2019-12-10 12:31:21,651 INFO sqlalchemy.engine.base.Engine SELECT appversion.id AS appversion_id, appversion.version AS appversion_version, appversion.`appUrl` AS `appversion_appUrl`, appversion.des AS appversion_des, appversion.`createTime` AS `appversion_createTime`, appversion.`lastModiftyTime` AS `appversion_lastModiftyTime`, appversion.type AS appversion_type
FROM appversion ORDER BY appversion.version DESC
LIMIT %s
2019-12-10 12:31:21,651 INFO sqlalchemy.engine.base.Engine (1,)
2019-12-10 12:31:21,661 INFO sqlalchemy.engine.base.Engine COMMIT
2019-12-10 12:31:21,680 INFO sqlalchemy.engine.base.Engine BEGIN (implicit)
2019-12-10 12:31:21,681 INFO sqlalchemy.engine.base.Engine SELECT appversion.id AS appversion_id, appversion.version AS appversion_version, appversion.`appUrl` AS `appversion_appUrl`, appversion.des AS appversion_des, appversion.`createTime` AS `appversion_createTime`, appversion.`lastModiftyTime` AS `appversion_lastModiftyTime`, appversion.type AS appversion_type
FROM appversion
WHERE appversion.id = %s
2019-12-10 12:31:21,681 INFO sqlalchemy.engine.base.Engine (1,)

4、但有时候(可能是时间略长些)commit后,再使用查询结果的对象,可能会出现报错:Instance <User at 0x32768d0> is not bound to a Session   

  此种情况可能是因为绑定的session已经被回收,导致无法再进行查询,所以出错。

5、综上所述,为安全起见,需要在查询结果后,加上 db.session.expunge(ret),断开查询结果与session的关系。让它成为一个本地实体,不会从缓存中清除,使用时候,就不会再查询。

6、但测试时候发现一个奇怪的问题,另外一个获取user的接口,和上面的代码几乎没什么区别,居然会自动rollback,这个让我百思不得其解。

  我的逻辑是取到查询结果(即用户)后,判断用户的状态字段是否为1,如果为1,就修改用户属性,然后commit,如果不是1,就不做操作,也没有调用rollback。

  但是我测试时候发现,如果不是1的时候,它会自动rollback。

或许这是sqlalchemy的高级功能?

7、总结:

  1、sqlalchemy的对象实体(model),和session建立了联系,你get、set这些model的时候,就算已经commit,也会重新自动和数据库建立连接(get的时候会重新select、set的时候会重新建立连接,等待你提交,如果你不提交,这个连接一直存在,最终会耗尽。),所以要谨慎使用model的字段,除非你确实明白自己在做什么,会发生什么。

  2、使用db.session.expunge会切断实体和session的关系。这个是个不错的用法。

  3、但我还是强烈建议自己再搞一套model,来做业务层逻辑。sqlalchemy的对象实体仅用来做数据库的操作。这样会避免很多时候,连接不小心没释放的坑。

 

关于flask-sqlalchemy的用法研究的更多相关文章

  1. flask SQLAlchemy中一对多的关系实现

    SQLAlchemy是Python中比较优秀的orm框架,在SQLAlchemy中定义了多种数据库表的对应关系, 其中一对多是一种比较常见的关系.利用flask sqlalchemy实现一对多的关系如 ...

  2. flask, SQLAlchemy, sqlite3 实现 RESTful API 的 todo list, 同时支持form操作

    flask, SQLAlchemy, sqlite3 实现 RESTful API, 同时支持form操作. 前端与后台的交互都采用json数据格式,原生javascript实现的ajax.其技术要点 ...

  3. flask建表遇到的错误: flask,sqlalchemy.exc.OperationalError: (MySQLdb._exceptions.OperationalError) (1071, 'Specified key was too long; max key length is 767 bytes')

    error:flask,sqlalchemy.exc.OperationalError: (MySQLdb._exceptions.OperationalError) (1071, 'Specifie ...

  4. Flask – SQLAlchemy成员增加

    目录 简介 结构 展示 技术 运行 代码 创建数据库表单 views视图 home主页 添加成员addnew.html 展示页show_all 简介 结构 $ tree -I "__pyca ...

  5. 关于Python的super用法研究

    一.问题的发现与提出 在Python类的方法(method)中,要调用父类的某个方法,在python 2.2以前,通常的写法如代码段1: 代码段1: class A:  def __init__(se ...

  6. Flask+SQLAlchemy+alembic+Flask-RESTful使用

    前言 其实准备把这篇删掉,先写Flask-restful相关的,后来想想大体框架还是先写出来,这两天踩了很多坑,有的谷歌也没有答案.一直摸索也总算是开始了. 正文 SQLAlchemy/alembic ...

  7. flask SQLALchemy外键及约束

    from flask import Flask,session from flask_sqlalchemy import SQLAlchemy import config app = Flask(__ ...

  8. python3 + flask + sqlalchemy +orm(3):多对多关系

    一篇文章有多个tag,一个tag也可以属于多篇文章,文章和tag存在多对多关系 config.py DEBUG = True #dialect+driver://root:1q2w3e4r5t@127 ...

  9. python3 + flask + sqlalchemy +orm(2):数据库中添加表

    往数据库中添加一张保存文章的表,表明为article,字段有id,title,content 同样一个配置文件:config.py DEBUG = True #dialect+driver://roo ...

随机推荐

  1. ITester软件测试小栈,快来点击领取你的能量值!

    日供一卒,功不唐捐,这不是一个非正常更新的ITester软件测试小栈,不定期分享软件测试相关,包括功能.接口.自动化.性能.专项.测试开发,简历指点,面试助攻,群而不党,和而不同,如趋同,且同行.

  2. [校内自测 NOIP模拟题] chenzeyu97要请客(单调栈)

    题目描述 chenzeyu97的家可以看成是一个n*m的矩阵,每块区域都有独一无二的海拔高度h(h>0)!其最大值为n*m. 现在他要选择一个子矩阵摆放一张桌子,在他眼里,这样摆放桌子的美观度为 ...

  3. 修改 Django Administration

    只需要在django项目下的APP下的admin.py重写以下几个变量即可,不需要改django源码 from django.contrib import adminadmin.site.site_t ...

  4. Java 读取Word批注中的文本和图片

    本文将介绍读取Word批注的方法,包括读取Word批注中的文本及图片.关于操作Word批注的方法还可以参考这两篇文章:Java 添加.回复.修改.删除Word批注:Java 给Word指定字符串添加批 ...

  5. [复现论文程序图]High Speed Continuous Variable Source-Independent Quantum Random Number Generation

    这次的任务是复现该文章的图2(C),过程如下. ①翻译了整篇文章,断断续续,花了3-4天时间. ②阅读文章,并且记录下每个符号的意义,记在单独的1个word文档里. ③开始编程,用的matlab201 ...

  6. 在代码生成工具Database2Sharp中使用ODP.NET(Oracle.ManagedDataAccess.dll)访问Oracle数据库,实现免安装Oracle客户端,兼容32位64位Oracle驱动

    由于我们开发的辅助工具Database2Sharp需要支持多种数据库,虽然我们一般使用SQLServer来开发应用较多,但是Oracle等其他数据库也是常用的数据库之一,因此也是支持使用Oracle等 ...

  7. ArcGIS 切片与矢量图图层顺序问题

    在项目中有个需求:根据图层索引添加图层 看到这个需求一下子想到 map.addLayer(layer,index?) 接口 但是问题出现了,我切片图加载顺序在矢量图之后就不行! map = new M ...

  8. tomcat启动窗口出现乱码

    tomcat启动窗口出现乱码     或者 idea运行服务器tomcat出现乱码 在tomcat的启动窗口打印的启动信息中包含了大量的中文乱码, 虽然这些对tomcat本身的使用没有任何影响,但却非 ...

  9. 使用Redis实现延时任务(一)

    使用Redis实现延时任务(一) 前提 最近在生产环境刚好遇到了延时任务的场景,调研了一下目前主流的方案,分析了一下优劣并且敲定了最终的方案.这篇文章记录了调研的过程,以及初步方案的实现. 候选方案对 ...

  10. C#Windows Forms (Demo.SYS)--xdd

    private void Show_background_picture()//随机更换背景 { ";//默认值 Random ran = new Random(); , );//返回一个1 ...