如果您的應用側主要使用Python語言,且數據庫連接創建頻繁(例如短連接場景)或連接數量較大(大于MySQL數據庫的連接數限制),您可以使用Python連接池DBUtils連接數據庫,降低連接建立頻率以減少數據庫主線程的開銷。
前提條件
應用服務器已安裝Python環境且Python版本在3.7至3.12。
已將服務器IP地址添加至RDS實例白名單中,詳情請參見設置IP白名單。
說明若您的應用程序部署在阿里云ECS服務器上,且ECS與RDS已實現內網互通(ECS與RDS實例的地域、VPC均相同),則無需設置IP白名單。
準備工作
安裝DBUtils:您需要通過以下命令在服務器上安裝Python連接池DBUtils,本教程中DBUtils版本為3.1.0,更多版本及信息請參見DBUtils。
pip install DBUtils==3.1.0
安裝PyMySQL:您需要通過以下命令安裝PyMySQL,以支持服務器連接數據庫。
pip install pymysql
使用DBUtils連接數據庫
導入相關模塊:在使用DBUtils連接數據庫前,您需要通過以下代碼導入相關模塊。
from dbutils.pooled_db import PooledDB import importlib import pymysql
構建
DBUtilsDemo
類:為了方便您后續的方法調用與管理,建議您新建一個DBUtilsDemo
類,在__init__
方法中設置連接池參數,并向該類中添加_connect
與_close
方法以便從連接池中獲取與歸還數據庫連接。class DBUtilsDemo: def __init__(self, url, user, password, database): db_config = { "host": url, "port": 3306, "user": user, "db": database, "password": password, "charset": "utf8", "connect_timeout": 3, "read_timeout": 10, "write_timeout": 10 } ''' DBUtils連接池常見參數的詳細說明請參見后文,以下為參數簡要說明: mincached: 池中閑置連接的初始數量(0表示啟動時不會創建連接)。 maxcached: 池中閑置連接的最大數量(0或None表示連接池大小沒有限制)。 maxshared: 共享連接的最大數量(0或None表示所有連接都是專用的)。 maxconnections: 一般允許的最大連接數量(0或None表示連接不受限制)。 blocking: 在超過最大連接數量時的行為。 maxusage: 單個連接的最大重用次數(0或None表示無限重用)。 ''' self.pooled = PooledDB(pymysql, maxcached=20, maxshared=0, maxconnections=100, maxusage=20, **db_config) # 從連接池獲取連接 def _connect(self): try: r = self.pooled.connection() return r except Exception as e: print("Failed to connect:" + str(e)) # 歸還連接到連接池 def _close(self, conn, stmt): if stmt: stmt.close() if conn: conn.close()
在
__main__
函數中初始化DBUtilsDemo
類并連接數據庫:DBUtilsDemo
類構造完成后,您可以在__main__
函數中初始化該類,并獲取數據庫連接。if __name__ == '__main__': # RDS MySQL實例連接地址,需要根據服務器情況選擇RDS內網/外網連接地址。 url = 'rm-bp**************.mysql.rds.aliyuncs.com' # 用戶名,根據實際情況做替換。 user = 'dbuser' # 密碼,根據實際情況做替換。 password = '****' # 連接的數據庫名稱,根據實際情況做替換。 database = 'dbtest' # 獲取連接池對象 poolUtils = DBUtilsDemo(url, user, password, database)
連接池常見參數配置
在使用DBUtils連接數據庫時,建議您根據下述內容為連接池設置合適的參數(在__init__
方法調用的PooledDB
函數中設置),使數據庫的運行更穩定高效。
為了最大程度地避免潛在的風險和不確定性,在將新的參數值用于生產環境前,建議您至少進行一輪完整的功能測試和性能測試,以確保系統穩定性和可靠性。
推薦配置的參數
推薦您在使用DBUtils連接池時設置以下參數,降低數據庫運行風險。
參數名 | 含義 | 默認值 | 推薦值 | 說明 |
maxcached | 池中閑置連接的最大數量。 | 0 | 20 |
|
maxusage | 單個連接的最大重用次數。 | None | 10~20 |
|
connect_timeout | 連接到數據庫的超時時間(秒)。 | 10 | 3 |
|
read_timeout | 從數據庫讀取的超時時間(秒)。 | None | 10~60 |
|
write_timeout | 寫入數據庫的超時時間(秒)。 | None | 10~60 |
|
可選擇配置的參數
使用DBUtils連接池時,您可以選擇性地配置以下參數,提升數據庫性能。
參數名 | 含義 | 默認值 | 推薦值 | 說明 |
maxconnections | 連接池允許的最大連接數量。 | 0 | 100 |
|
保持默認配置的參數
對于以下常見的連接池參數,您可以選擇直接使用默認配置或根據自身需求調整參數。
參數名 | 含義 | 默認值 | 推薦值 | 說明 |
mincached | 池中閑置連接的初始數量。 | 0 | / |
|
maxshared | 共享連接的最大數量。 | 0 | / |
|
blocking | 超過最大連接數量時的處理方法。 | False | / |
|
setsession | 連接被創建時執行的 SQL 語句 | None | / | 該參數可以用來設置會話級別的參數或者執行其他初始化操作。 |
reset | 連接被放回連接池時,是否需要重置連接狀態。 | True | / |
|
failures | 數據庫連接失敗時的重連次數。 | None | / | / |
ping | 連接池在空閑連接時執行的心跳檢測操作。 | 1 | / | 該參數用來驗證連接可用性。 |
后續數據庫操作
您可以在DBUtilsDemo
類中添加自定義方法處理讀寫請求,滿足對數據庫的操作需求。
讀請求處理
1. 添加自定義方法
您需要在DBUtilsDemo
類中添加自定義方法處理數據庫讀請求,本文以查詢單條記錄與查詢多條記錄為例。
查詢單條記錄
def select_row(self, sql): connection = self._connect() statement = None try: statement = connection.cursor() statement.execute(sql) row = statement.fetchone() return row except Exception as e: print(e) finally: self._close(connection, statement)
查詢多條記錄
def select_rows(self, sql): connection = self._connect() statement = None try: statement = connection.cursor() statement.execute(sql) rows = statement.fetchall() return rows except Exception as e: print(e) finally: self._close(connection, statement)
2. 調用自定義方法
您需要在__main__
函數中調用該方法進行數據查詢。
if __name__ == '__main__':
# 配置連接參數并連接數據庫
url = 'rm-bp**************.mysql.rds.aliyuncs.com'
user = 'dbuser'
password = '****'
database = 'dbtest'
poolUtils = DBUtilsDemo(url, user, password, database)
# 查詢單條記錄
row = poolUtils.select_row("select * from tb where id = 'i001' limit 1")
print(row)
# 查詢多條記錄
rows = poolUtils.select_rows("select * from tb")
print(rows)
寫請求處理
1. 添加自定義方法
您需要在DBUtilsDemo
類中添加自定義方法處理數據庫寫請求(包括INSERT
、UPDATE
、DELETE
、CREATE TABLE
等命令),本文以帶參數寫請求與不帶參數寫請求為例。
帶參數寫請求處理
def upsert_data_prams(self, sql_upsert, params): connection = self._connect() statement = None try: statement = connection.cursor() statement.execute(sql_upsert, params) connection.commit() except Exception as e: print(e) finally: self._close(connection, statement)
不帶參數寫請求處理
def upsert_data(self, sql_upsert): connection = self._connect() statement = None try: statement = connection.cursor() statement.execute(sql_upsert) connection.commit() except Exception as e: print(e) finally: self._close(connection, statement)
2. 調用自定義方法
您需要在__main__
函數中調用該方法執行SQL語句。
if __name__ == '__main__':
# 配置連接參數并連接數據庫
url = 'rm-bp**************.mysql.rds.aliyuncs.com'
user = 'dbuser'
password = '****'
database = 'dbtest'
poolUtils = DBUtilsDemo(url, user, password, database)
# 不帶參數寫請求處理
poolUtils.upsert_data("insert into tb(id,name,address) values ('i001','n001','a001')")
# 帶參數寫請求處理
params = ['i002', 'n002', 'a002']
poolUtils.upsert_data_prams("insert into tb(id,name,address) values (%s,%s,%s)", params)
相關文檔
Java連接池:使用Java連接池Druid連接數據庫
RDS MySQL數據庫代理中的連接池功能:RDS MySQL設置連接池