惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
月光博客
月光博客
The Last Watchdog
The Last Watchdog
T
Tenable Blog
C
Cyber Attacks, Cyber Crime and Cyber Security
C
CXSECURITY Database RSS Feed - CXSecurity.com
Simon Willison's Weblog
Simon Willison's Weblog
V
Vulnerabilities – Threatpost
F
Fortinet All Blogs
Microsoft Security Blog
Microsoft Security Blog
A
Arctic Wolf
云风的 BLOG
云风的 BLOG
Know Your Adversary
Know Your Adversary
P
Palo Alto Networks Blog
GbyAI
GbyAI
阮一峰的网络日志
阮一峰的网络日志
The GitHub Blog
The GitHub Blog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
U
Unit 42
MyScale Blog
MyScale Blog
B
Blog
Spread Privacy
Spread Privacy
S
Schneier on Security
Project Zero
Project Zero
L
LINUX DO - 热门话题
M
MIT News - Artificial intelligence
F
Full Disclosure
WordPress大学
WordPress大学
Apple Machine Learning Research
Apple Machine Learning Research
Cyberwarzone
Cyberwarzone
AWS News Blog
AWS News Blog
aimingoo的专栏
aimingoo的专栏
博客园 - 三生石上(FineUI控件)
C
Cybersecurity and Infrastructure Security Agency CISA
Hugging Face - Blog
Hugging Face - Blog
Security Latest
Security Latest
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
T
Tailwind CSS Blog
K
Kaspersky official blog
Recent Announcements
Recent Announcements
NISL@THU
NISL@THU
Cisco Talos Blog
Cisco Talos Blog
S
Securelist
P
Privacy & Cybersecurity Law Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
T
The Exploit Database - CXSecurity.com
V
Visual Studio Blog
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Webroot Blog
Webroot Blog

博客园 - 清虚真人

[原]跟我学silverlight系列教程[1]—wpf/silverlight体系架构和运行机制 [原]跟我学silverlight系列教程 sql2005 数据库没有完全关闭,无法重新生成日志 IIS中网站出错 javascript获取滚动条位置 - 清虚真人 - 博客园 .Net framework [转载]My97DatePicker在Frame中无法打开站点 输出datagrid的内容到excel - 清虚真人 - 博客园 sql select的时候按特定的顺序排序 vs2008 安装Silverlight tools遇到的崩溃问题。。。 关于.NET中的Server push技术 .net 几种序列化类的比较 asp.net ajax实现(—):Jquery+Json WPF中BitMapEffect的性能问题 我写的PageDataSurce分页的 asp.net页面执行机制 关于服务器端控件的attributes属性的奇怪问题 关于使用javascript+asp.net实现多文件上传的若干问题 正则表达式相关教程
关于flask-sqlalchemy的用法研究
清虚真人 · 2019-12-10 · via 博客园 - 清虚真人

最近使用到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的对象实体仅用来做数据库的操作。这样会避免很多时候,连接不小心没释放的坑。