我该如何在多模块Python应用中建立和管理数据库连接?
我们有一个Python应用程序,里面有二十多个模块,其中大部分模块被多个网页和控制台应用共享。
我一直不太清楚在多模块的Python应用中,建立和管理数据库连接的最佳做法是什么。举个例子:
我有一个模块专门定义用户的对象类。这个模块里有很多函数,用来在数据库中创建、删除和更新用户。这个users.py模块被引入到三个地方:1)一个基于控制台的工具,2)一个基于web.py的网页应用,3)一个不断运行的守护进程。
这三个应用的生命周期都不一样。守护进程可以打开一个连接并保持它一直打开。控制台工具连接后做完工作就结束了。当然,HTTP请求是一次性的,但网页服务器本身是一个守护进程。
目前我是在Users类的每个函数内部打开、使用然后关闭连接。这看起来效率不高,但在所有例子中都能正常工作。作为测试,我尝试过在整个模块中声明并打开一个全局连接。还有一个选择是在最上层的应用中创建连接,然后在实例化类时传递引用,但我觉得这个主意最糟糕。
我知道每个应用的架构都不一样。我只是想知道有没有什么最佳实践,或者说如果有的话是什么?
2 个回答
MySQL的连接速度比较快,所以这可能不是个大问题(也就是说,你应该自己测一下)。大多数其他数据库在建立连接时需要消耗更多的资源。
每次需要连接时创建一个新的连接是最安全的做法,也是一个不错的选择。有些数据库库,比如SqlAlchemy,内置了连接池,可以自动帮你正确地重用连接。
如果你决定保持一个连接活着,以便可以重复使用,有几个要注意的点:
只用来读取的连接比用来修改数据库数据的连接更容易重用。
当你在一个连接上开始一个事务时,要小心,确保在你使用这个连接的时候,其他的东西不能再使用它。
长时间闲置的连接会变得不活跃,可能会被关闭,所以如果你要重用一个连接,需要检查它是否仍然“活着”,比如可以通过发送“select 1”来验证是否能得到结果。
我个人不建议自己实现连接池的算法。因为当出现问题时,调试起来非常困难。更好的选择是使用一个已经为你处理好这些的数据库库。
最好的方法是在你需要进行一些操作的时候(比如获取或更新数据)打开一个连接;处理数据后,再把它一次性写回数据库,这个过程只用一个查询(这对性能非常重要),然后再关闭连接。打开连接的过程其实很轻松。
在性能方面,有一些常见的误区:
- 在你不一定会和数据库互动的时候打开它
- 使用选择器获取比你需要的数据更多的信息(比如,获取所有用户的数据,然后在Python中进行筛选,而不是直接让MySQL帮你过滤掉不需要的数据)
- 写入那些没有改变的值(比如,更新用户资料的所有信息,而实际上只改了邮箱)
- 每个字段都单独更新服务器(比如,打开数据库,更新用户邮箱,关闭数据库,再打开数据库,更新用户密码,关闭数据库,接着再打开……你懂的)
总之,打开数据库的次数并不重要,重要的是你执行了多少个查询。如果你能让你的代码把相关的查询合并在一起,那你就成功了。