我似乎无法让我的Flask应用程序关闭或重新使用数据库连接。我使用Postgresql 9.1.3和
- Flask==0.8
- Flask-sqlAlchemy==0.16
- psycopg2==2.4.5
当我的测试套件运行打开的连接数爬到20(在postgresql.conf中的max_connections设置),然后我看到:
- OperationalError: (OperationalError) FATAL: sorry,too many clients already
- None None
我已经将代码缩小到只需调用create_all和drop_all(但不会发出任何sql,因为没有模型)。
我看到在日志中检入和取出的连接:
- DEBUG:sqlalchemy.pool.QueuePool:Connection <connection object at 0x101c1dff0; dsn: 'dbname=cx_test host=localhost',closed: 0> checked out from pool
- DEBUG:sqlalchemy.pool.QueuePool:Connection <connection object at 0x101c1dff0; dsn: 'dbname=cx_test host=localhost',closed: 0> being returned to pool
- WARNING:root:impl <-------- That's the test running
- DEBUG:sqlalchemy.pool.QueuePool:Connection <connection object at 0x101c1dff0; dsn: 'dbname=cx_test host=localhost',closed: 0> being returned to pool
对于每个测试运行,连接的地址(“xyz的连接对象”部分)是不同的。我怀疑这与问题有关,但我不知道如何进一步调查。
下面的代码在新的venv中再现了问题:
- from flask import Flask
- from flask.ext.sqlalchemy import sqlAlchemy
- from unittest import TestCase
- import logging
- logging.basicConfig(level=logging.DEBUG)
- logging.getLogger('sqlalchemy.pool').setLevel(logging.DEBUG)
- logging.getLogger('sqlalchemy.engine').setLevel(logging.DEBUG)
- logging.getLogger('sqlalchemy.dialects').setLevel(logging.DEBUG)
- logging.getLogger('sqlalchemy.orm').setLevel(logging.DEBUG)
- db = sqlAlchemy()
- def create_app(config=None):
- app = Flask(__name__)
- app.config.from_object(config)
- db.init_app(app)
- return app
- class AppTestCase(TestCase):
- sqlALCHEMY_DATABASE_URI = "postgresql://localhost/cx_test"
- TESTING = True
- def create_app(self):
- return create_app(self)
- def setUp(self):
- self.app = self.create_app()
- self.client = self.app.test_client()
- self._ctx = self.app.test_request_context()
- self._ctx.push()
- db.create_all()
- def tearDown(self):
- db.session.remove()
- db.drop_all()
- self._ctx.pop()
- class TestModel(AppTestCase):
- def impl(self):
- logging.warn("impl")
- pass
- def test_01(self):
- self.impl()
- def test_02(self):
- self.impl()
- def test_03(self):
- self.impl()
- def test_04(self):
- self.impl()
- def test_05(self):
- self.impl()
- def test_06(self):
- self.impl()
- def test_07(self):
- self.impl()
- def test_08(self):
- self.impl()
- def test_09(self):
- self.impl()
- def test_10(self):
- self.impl()
- def test_11(self):
- self.impl()
- def test_12(self):
- self.impl()
- def test_13(self):
- self.impl()
- def test_14(self):
- self.impl()
- def test_15(self):
- self.impl()
- def test_16(self):
- self.impl()
- def test_17(self):
- self.impl()
- def test_18(self):
- self.impl()
- def test_19(self):
- self.impl()
- if __name__ == "__main__":
- import unittest
- unittest.main()
这是我第一次在烧瓶中使用应用程序工厂,我从Flask-SQLAlchemy docs.部分复制了这个代码。Elseware这些文档提到在错误的上下文中使用数据库会导致连接泄漏 – 也许我正在做不正确的init?