SQLAlchemy pre-ping 機制
Posted on Jun 5, 2019 in Python 模組/套件推薦 by Amo Chen ‐ 2 min read
Connection Pool 是資料庫連線管理的機制,用來節省資料庫連線的成本,達到較高的資源利用效益。 Connection Pool 會事先與資料庫一次建立多個連線(connection),並維持住這些連線,每當應用程式(Application)需要操作資料庫時,就會從 Connection Pool 中提供(checkout)連線給應用程式使用。
但是資料庫連線也有斷線的可能,那麼要如何確保從 Connection Pool 取得的連線是可用的呢?
其中一種確定連線可用的機制就是 Pre-ping 。
本文就來談談 Pre-ping 與 SQLAlchemy 的 Pre-ping 如何設定。
本文環境
- MySQL 5.7
- Python 3.6.5
- SQLAlchemy 1.3.3
$ pip install SQLAlchemy
Pre-ping
Pre-ping 說來簡單,就是每次從 Connection Pool 取得連線時,就試著執行一次相當於 SELECT 1
的 SQL ,如果有問題,就可以重新建立新的連線取代失效的連線。
值得注意的是雖然 Pre-ping 可以確保從 Connection Pool 取得的連線可用,但是 Pre-ping 並無法解決執行資料庫操作到一半連線中斷的問題。
SQLAlchemy
SQLAlchemy 的 pre-ping 在 create_engine() 時設定,預設是沒有開啟 pre-ping 的,得加上參數 pool_pre_ping=True
才行:
engine = create_engine("mysql+pymysql://root:@127.0.0.1:3306/db", pool_pre_ping=True)
session = sessionmaker(bind=engine)()
session.execute('SELECT 1 + 1')
session.commit()
順便一提的是, pre-ping 的 log 並不會顯示在 SQLAlchemy 的 log 紀錄中。
the “SELECT 1” emitted by “pre-ping” is invoked within the scope of the connection pool / dialect, using a very short codepath for minimal Python latency. As such, this statement is not logged in the SQL echo output, and will not show up in SQLAlchemy’s engine logging.
Flask-SQLAlchemy
同場加映,如果是利用 Flask 開發 Web 應用的開發者們,應該都會使用 Flask-SQLAlchemy 套件進行開發。
如果想要針對該套件開啟 pre-ping 功能的話,就得自行將該套件提供的 SQLAlchemy 類別再包裝一層:
from flask_sqlalchemy import SQLAlchemy as _BaseSQLAlchemy
class SQLAlchemy(_BaseSQLAlchemy):
def apply_pool_defaults(self, app, options):
super(SQLAlchemy, self).apply_pool_defaults(app, options)
options['pool_pre_ping'] = True
db = SQLAlchemy()
以上!
Happy Coding!
References
https://docs.sqlalchemy.org/en/13/core/engines.html#sqlalchemy.create_engine.params.pool_pre_ping