python自制簡易mysql連接池的實現示例
今天我們來說一點不一樣的, 使用python語言手擼mysql連接池.
連接池是什么?
連接池是創(chuàng)建和管理一個連接的緩沖池的技術,這些連接準備好被任何需要它們的線程使用。在并發(fā)量足夠時連接池一般比直接連接性能更優(yōu), 不僅提高了性能的同時還管理了寶貴的資源.
為什么需要連接池?
討論這個問題時, 我們需要先了解高并發(fā)導致服務器卡頓的原因出在哪里.
正常情況下, 每當一位用戶使用各類終端連接到服務器的時候, 服務器都需要開辟一片內存為其服務, 每當一個請求從前端傳入都需在mysql之間創(chuàng)建一條連接. 然而過多的連接會導致服務器卡頓內存占用過高, 這時候就需要連接池對所有連接狀態(tài)進行管理, 合理分配&回收資源.
簡單說就是使用連接池技術可用減少服務器壓力.
連接池的原理是什么?
連接池主要需要兩個參數,默認連接數、最大連接數
- 當服務啟動時, 首先創(chuàng)建默認連接數的空閑連接放入池中.
- 當用戶需要連接時, 首先查看池中是否有空閑連接.
- 如果有: 由連接池分配從池中取出一個空閑連接交付用戶使用.
- 如果沒有: 查看當前存活的所有連接總數是否大于最大連接.
- 如果小于: 創(chuàng)建新連接交付用戶使用.
- 如果等于: 線程阻塞, 等待有空閑連接再交予用戶.
- 當用戶用完連接后, 查看當前存活連接數是否大于默認值.
- 如果小于等于: 將此條連接重新放入空閑池中, 等待下一次使用.
- 如果大于: 將此條連接釋放銷毀, 不放入池中.
使用python語言自制簡易mysql連接池
這里, 我們需要 ThemisPool.py 連接池本身, db.cnf 配置文件, 其目錄路徑如下:
# 推薦目錄格式, ThemisPool.py & db.cnf 只需要在同級目錄下即可
[your python project]
|
|
|-- util
|
|-- db.cnf
|
|-- ThemisPool.py
ThemisPool.py
# 導入依賴
# mysql連接基本庫
import pymysql
# 讀取配置文件所需要的庫
import configparser
import os
# 線程管理所需要的庫
import threading
# 創(chuàng)建配置類用戶讀取配置文件
class Config(object):
def __init__(self, configFileName='db.cnf'):
file = os.path.join(os.path.dirname(__file__), configFileName)
self.config = configparser.ConfigParser()
self.config.read(file)
def getSections(self):
return self.config.sections()
def getOptions(self, section):
return self.config.options(section)
def getContent(self, section):
result = {}
for option in self.getOptions(section):
value = self.config.get(section, option)
result[option] = int(value) if value.isdigit() else value
return result
# 將連接所需要的參數封裝在對象中
# 依次為: 數據庫密碼、需要連接的庫名、主機地址[默認 localhost]、端口號[默認 3306]、初始化連接數[默認 3]、最大連接數[默認 6]
class parameter(object):
def __init__(self, password, database, host="localhost",port="3306" user="root", initsize=3, maxsize=6):
self.host = str(host)
self.port = int(port)
self.user = str(user)
self.password = str(password)
self.database = str(database)
self.maxsize = int(maxsize)
self.initsize = int(initsize)
# 連接池
class ThemisPool(parameter):
def __init__(self, fileName='db.cnf', configName='mysql'):
# 加載配置文件, 配置文件名默認為 'db.cnf', 配置標簽默認為 'mysql'
self.config = Config(fileName).getContent(configName)
super(ThemisPool, self).__init__(**self.config)
# 創(chuàng)建隊列作為 池
self.pool = queue.Queue(maxsize=self.maxsize)
self.idleSize = self.initsize
# 創(chuàng)建線程鎖
self._lock = threading.Lock()
# 初始化連接池
for i in range(self.initsize):
# 創(chuàng)建 初始化連接數 數量的連接放入池中
self.pool.put(self.createConn())
# 啟動日志
print('\033[1;32m ThemisPool connect database {database}, login is {user} \033[0m'.format(database=self.database,
user=self.user))
# 生產連接
def createConn(self):
# 使用mysql基本類
# pymysql.connect 參數這里不做解釋,具體請查閱官網 https://pypi.org/project/PyMySQL/
return pymysql.connect(host=self.host,
port=self.port,
user=self.user,
password=self.password,
database=self.database,
charset='utf8')
# 獲取連接
def getConn(self):
self._lock.acquire()
try:
# 如果池中連接夠直接獲取
if not self.pool.empty():
self.idleSize -= 1
else:
# 否則重新添加新連接
if self.idleSize < self.maxsize:
self.idleSize += 1
self.pool.put(self.createConn())
finally:
self._lock.release()
return self.pool.get()
# 釋放連接
def releaseCon(self, conn=None):
try:
self._lock.acquire()
# 如果池中大于初始值就將多余關閉,否則重新放入池中
if self.pool.qsize() < self.initsize:
self.pool.put(conn)
self.idleSize += 1
else:
try:
# 取出多余連接并關閉
surplus = self.pool.get()
surplus.close()
del surplus
self.idleSize -= 1
except pymysql.ProgrammingError as e:
raise e
finally:
self._lock.release()
# 拉取數據(查詢)
# 可用語句類型 (select)
def fetchone(self, sql):
themis = None
cursor = None
try:
themis = self.getConn()
cursor = themis.cursor()
cursor.execute(sql)
return cursor.fetchall()
except pymysql.ProgrammingError as e:
raise e
except pymysql.OperationalError as e:
raise e
except pymysql.Error as e:
raise e
finally:
cursor.close()
self.releaseCon(themis)
# 更新
# 可用語句類型 (insert, update, delete)
def update(self, sql):
themis = None
cursor = None
try:
themis = self.getConn()
cursor = themis.cursor()
cursor.execute(sql)
return cursor.lastrowid
except pymysql.ProgrammingError as e:
raise e
except pymysql.OperationalError as e:
raise e
except pymysql.Error as e:
raise e
finally:
themis.commit()
cursor.close()
self.releaseCon(themis)
# 釋放連接池本身
def __del__(self):
try:
while True:
conn = self.pool.get_nowait()
if conn:
conn.close()
except queue.Empty:
pass
db.cnf 配置文件
[mysql] host = localhost user = root password = 12345678 database = practice initsize = 3 maxsize = 6
所有配置屬性
| 參數 | 說明 | 類型 | 默認值 |
|---|---|---|---|
| host | 主機地址 | str | localhost |
| port | 端口號 | int | 3306 |
| user | mysql登錄用戶名 | str | root |
| password | mysql登錄密碼 | str | - |
| database | 訪問庫名 | str | - |
| initsize | 初始化連接數 | int | 3 |
| maxsize | 最大連接數 | int | 6 |
開始使用
from util.ThemisPool import ThemisPool # 初始化ThemisPool連接池 (Initialize the ThemisPool connection pool) db = ThemisPool() # 查詢拉取數據,函數會直接返回數據 (Query pull data.It returns data directly) selectSql = "select * from user;" data = db.fetchone(selectSql) # 增、刪、改語句, 如果有使用mysql自增長插入的值函數會返回自增長的數據 (insert,upate delete and alter. If there is a value function inserted using mysql self-growth, it will return self-growth data) insertSql = "insert into user values(null,'user001','123456')" id = db.update(selectSql)
自定義配置文件名 & 配置標簽
配置文件名默認為 db.cnf, 配置標簽默認為 [mysql]
例如自定義配置文件名為 myDB.cnf, 配置標簽為 [mysqlConfig]
# myDB.cnf [mysqlConfig] host = localhost user = root password = 12345678 database = practice initsize = 3 maxsize = 6
# 使用時 ... db = ThemisPool(fileName='myDB.cnf', configName='mysqlConfig') ...
命名思路
Themis(忒彌斯) 取名來自于古希臘神話中秩序女神的名字, 就如同連接池的作用一樣, 管理所有用戶的連接, 減少不必要的損耗。
GitHub地址
以上就是本次的全部內容, 下版本將會解決 python 不能對 datetime 類型的數據進行 json格式化 的問題, 并將它集成進來
到此這篇關于python自制簡易mysql連接池的實現示例的文章就介紹到這了,更多相關python mysql連接池內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

