如何在MySQL中关闭SQLAlchemy连接

107

这是我想运行的示例代码:

for i in range(1,2000):
    db = create_engine('mysql://root@localhost/test_database')
    conn = db.connect()
    #some simple data operations
    conn.close()
    db.dispose()
有没有一种方法可以在不从MySQL获得“Too many connections”错误的情况下运行这个程序? 我已经知道可以通过其他方式处理连接或者使用连接池。我只是想了解如何正确关闭sqlalchemy的连接。

1
在我看来,你已经涵盖了两种选择:池化或循环外。 - xQbert
2
看起来你的例子已经没有“Too many connections”问题了(因为连接在循环内部打开/关闭)。 - Romuald Brunet
@martincho,即使我也无法从你的代码中生成“连接过多”的错误 :(。 - Nilesh
4个回答

196

以下是正确编写该代码的方法:

db = create_engine('mysql://root@localhost/test_database')
for i in range(1,2000):
    conn = db.connect()
    #some simple data operations
    conn.close()
db.dispose()

也就是说,Engine 不仅是连接的工厂,同时也是连接池。当你执行 conn.close() 时,连接会被返回到 Engine 中的连接池,而不是真正被关闭。

如果你确实想要关闭连接,即不使用连接池,请通过 NullPool 禁用连接池:

from sqlalchemy.pool import NullPool
db = create_engine('mysql://root@localhost/test_database', poolclass=NullPool)

通过上述Engine配置,每次调用conn.close()将关闭底层的DBAPI连接。

如果你想要在每次调用时连接到不同的数据库,也就是说,你硬编码的"localhost/test_database"只是一个例子,实际上有许多不同的数据库,那么使用dispose()方法是可以的;它将关闭所有未从池中检出的连接。

在所有上述情况下,重要的是通过close()关闭Connection对象。如果您正在使用任何类型的“无连接”执行,即engine.execute()statement.execute(),则应完全读取来自该执行调用的ResultProxy对象,或者通过close()显式关闭。仍然打开的ConnectionResultProxy将阻止NullPooldispose()方法关闭每个最后一个连接。


10
dispose()!我需要它来关闭会话,因为session.close()不够用。根据我的经验,我建议将此添加到SQLAlchemy文档中,因为如何正确关闭会话并不清楚。 - fedorqui
3
按照文档所述,请调用close()方法。对于普通的SQLAlchemy使用,通常不需要显式地调用dispose()方法。如果您遇到问题,请随时通过邮件列表(http://groups.google.com/group/sqlalchemy) 提供有关您特定问题的信息。也许您在Session上执行了一些特殊指令(例如"SET"),在使用连接池时这些指令没有被清除(但有另外一种处理方式)。 - zzzeek
我刚刚在一个新的问题中发布了信息:如何正确关闭SQLAlchemy会话? 如果您愿意在这里回答,那就太好了。否则我会通过邮件列表联系您。非常感谢! - fedorqui
@zzzeek 有点晚了,但我想感谢您的杰出工作。我已成为您的赞助人!(任何其他阅读此内容的人也应该加入:https://www.patreon.com/join/zzzeek) - aaron

10

我尝试找到解决方案来解决与数据库无关的问题(必须在forking之前断开连接)。

你需要从连接池中使连接失效

以你的例子为例:

for i in range(1,2000):
    db = create_engine('mysql://root@localhost/test_database')
    conn = db.connect()
    # some simple data operations
    # session.close() if needed
    conn.invalidate()
    db.dispose()

6

我使用这一个

engine = create_engine('...')
with engine.connect() as conn:
    conn.execute(text(f"CREATE SCHEMA IF NOT EXISTS...")
engine.dispose()

1
使用 engine.connect() 连接数据库后,执行完操作后连接会自动关闭吗? - Mike Weston

-1
在我的情况下,这些总是有效的,我能够关闭!因此,在关闭之前使用invalidate()就可以解决问题。否则,close()很烦人。
conn = engine.raw_connection()  
conn.get_warnings  = True
curSql = xx_tmpsql
myresults = cur.execute(curSql, multi=True)
print("Warnings: #####")
print(cur.fetchwarnings())
for curresult in myresults:
    print(curresult)
    if curresult.with_rows:
        print(curresult.column_names)
        print(curresult.fetchall())
    else:
        print("no rows returned")
cur.close()
conn.invalidate()
conn.close()     
engine.dispose()

你什么时候实例化cur? - Cristián Vargas Acevedo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接