1.疑问来源
时常使用 sqlalchemy 建立 engine 连接 mysql 或者 postgres ,然后利用 pandas 与数据库进行交互。一般情况下,使用结束后,就随手将 jupyter notebook 关闭了,从来没有刻意的去管 sqlalchemy engine 没有关闭后,是否会造成数据库资源浪费的问题,于是就有了这个疑问。
2.疑问解决
to be continued
前期结论:
- 如果不是疯狂的建立连接,MySQL/Postgreps 会自动关闭连接。
3.资料汇总
3.1 con.close() vs con.dispose()
Q1:
- pandas.read_sql 函数中,执行完毕后,con参数(SQLAlchemy connectable)是否会释放资源——con.close()
- 整体 python 脚本执行结束后,有无必要释放 con —— con.dispose()
- SQLAlchemy create_engine 的 engine 是什么?
- Engine Configuration, 中文版:引擎配置
pandas.read_sql(sql, con, index_col=None, coerce_float=True, params=None, parse_dates=None, columns=None, chunksize=None)
con : SQLAlchemy connectable (engine/connection) or database string URI
or DBAPI2 connection (fallback mode)
Using SQLAlchemy makes it possible to use any DB supported by that library. If a DBAPI2 object, only sqlite3 is supported.
3.1.1 引子——他山之石
来自 python如何正确关闭数据库的链接,尤其sqlalchemy connection in MySQL
from sqlalchemy import create_engine
dataIn2File.to_sql
中dataIn2File
为 pandas 的 DataFrame 数据类型
现在,基本上大家都采用python3。而python3中,用的较多的模块是sqlalchemy ,来链接mysql。然而,一般的例子中都没有涉及关闭链接。
例如:
conn = create_engine('mysql+pymysql:user:passwd@host:port/db?charset=etf-8')
try:
dataIn2File.to_sql(table_name,con=conn,if_exists='append',index=False)
except Exception as ee:
logger.error('fileToMysql fialed',ee)
traceback.print_exc()
以上代码就没有关闭过conn,导致数据库的链接越来越多,最后无法新建链接。
查询过相关知识,发现了以下两种方式:
conn = create_engine('mysql+pymysql:user:passwd@host:port/db?charset=etf-8')
con = conn.connect()
try:
dataIn2File.to_sql(table_name,con=con,if_exists='append',index=False)
except Exception as ee:
logger.error('fileToMysql fialed',ee)
traceback.print_exc()
finally:
con.close()
或者
conn = create_engine('mysql+pymysql:user:passwd@host:port/db?charset=etf-8')
con = conn.connect()
try:
dataIn2File.to_sql(table_name,con=con,if_exists='append',index=False)
except Exception as ee:
logger.error('fileToMysql fialed',ee)
traceback.print_exc()
finally:
con.close()
然而,事实上,链接依旧没有关闭。若要真正关闭链接,则需要采用:conn.dispose()
conn = create_engine('mysql+pymysql:user:passwd@host:port/db?charset=etf-8')
try:
dataIn2File.to_sql(table_name,con=conn,if_exists='append',index=False)
except Exception as ee:
logger.error('fileToMysql fialed',ee)
traceback.print_exc()
finally:
conn.dispose()
经过1个小时多的探索,终于大功告成。
3.2 Google 探索
Search word:
- how long postgres auto close connection
- how long mysql auto close connection
3.2.1 MySQL自动关闭空闲连接时间
MySQL默认自动关闭连接时间(interactive_timeout, wait_timeout )为8小时
How long is “too long” for MySQL Connections to sleep?
mysqld
will timeout database connections based on two server options:
1. interactive_timeout
The number of seconds the server waits for activity on an interactive connection before closing it. An interactive client is defined as a client that uses the CLIENT_INTERACTIVE option to mysql_real_connect(). See also wait_timeout.
2. wait_timeout
The number of seconds the server waits for activity on a noninteractive connection before closing it.
On thread startup, the session wait_timeout value is initialized from the global wait_timeout value or from the global interactive_timeout value, depending on the type of client (as defined by the CLIENT_INTERACTIVE connect option to mysql_real_connect()). See also interactive_timeout.
Both are 28,800 seconds (8 hours) by default.
You can set these options in /etc/my.cnf
If your connections are persistent (opened via mysql_pconnect
) you could lower these numbers to something reasonable like 600 (10 minutes) or even 60 (1 minute). Or, if your app works just fine, you can leave the default. This is up to you.
You must set these as follows in my.cnf
(takes effect after mysqld
is restarted):
[mysqld]
interactive_timeout=180
wait_timeout=180
If you do not want to restart mysql, then run these two commands:
SET GLOBAL interactive_timeout = 180;
SET GLOBAL wait_timeout = 180;
This will not close the connections already open. This will cause new connections to close in 180 seconds.