python自制簡(jiǎn)易mysql連接池的實(shí)現(xiàn)示例
今天我們來(lái)說(shuō)一點(diǎn)不一樣的, 使用python語(yǔ)言手?jǐn)]mysql連接池.
連接池是什么?
連接池是創(chuàng)建和管理一個(gè)連接的緩沖池的技術(shù),這些連接準(zhǔn)備好被任何需要它們的線程使用。在并發(fā)量足夠時(shí)連接池一般比直接連接性能更優(yōu), 不僅提高了性能的同時(shí)還管理了寶貴的資源.
為什么需要連接池?
討論這個(gè)問(wèn)題時(shí), 我們需要先了解高并發(fā)導(dǎo)致服務(wù)器卡頓的原因出在哪里.
正常情況下, 每當(dāng)一位用戶使用各類終端連接到服務(wù)器的時(shí)候, 服務(wù)器都需要開(kāi)辟一片內(nèi)存為其服務(wù), 每當(dāng)一個(gè)請(qǐng)求從前端傳入都需在mysql之間創(chuàng)建一條連接. 然而過(guò)多的連接會(huì)導(dǎo)致服務(wù)器卡頓內(nèi)存占用過(guò)高, 這時(shí)候就需要連接池對(duì)所有連接狀態(tài)進(jìn)行管理, 合理分配&回收資源.
簡(jiǎn)單說(shuō)就是使用連接池技術(shù)可用減少服務(wù)器壓力.
連接池的原理是什么?
連接池主要需要兩個(gè)參數(shù),默認(rèn)連接數(shù)、最大連接數(shù)
- 當(dāng)服務(wù)啟動(dòng)時(shí), 首先創(chuàng)建默認(rèn)連接數(shù)的空閑連接放入池中.
- 當(dāng)用戶需要連接時(shí), 首先查看池中是否有空閑連接.
- 如果有: 由連接池分配從池中取出一個(gè)空閑連接交付用戶使用.
- 如果沒(méi)有: 查看當(dāng)前存活的所有連接總數(shù)是否大于最大連接.
- 如果小于: 創(chuàng)建新連接交付用戶使用.
- 如果等于: 線程阻塞, 等待有空閑連接再交予用戶.
- 當(dāng)用戶用完連接后, 查看當(dāng)前存活連接數(shù)是否大于默認(rèn)值.
- 如果小于等于: 將此條連接重新放入空閑池中, 等待下一次使用.
- 如果大于: 將此條連接釋放銷毀, 不放入池中.
使用python語(yǔ)言自制簡(jiǎn)易mysql連接池
這里, 我們需要 ThemisPool.py 連接池本身, db.cnf 配置文件, 其目錄路徑如下:
# 推薦目錄格式, ThemisPool.py & db.cnf 只需要在同級(jí)目錄下即可 [your python project] | | |-- util | |-- db.cnf | |-- ThemisPool.py
ThemisPool.py
# 導(dǎo)入依賴 # mysql連接基本庫(kù) import pymysql # 讀取配置文件所需要的庫(kù) import configparser import os # 線程管理所需要的庫(kù) 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 # 將連接所需要的參數(shù)封裝在對(duì)象中 # 依次為: 數(shù)據(jù)庫(kù)密碼、需要連接的庫(kù)名、主機(jī)地址[默認(rèn) localhost]、端口號(hào)[默認(rèn) 3306]、初始化連接數(shù)[默認(rèn) 3]、最大連接數(shù)[默認(rèn) 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'): # 加載配置文件, 配置文件名默認(rèn)為 'db.cnf', 配置標(biāo)簽?zāi)J(rèn)為 'mysql' self.config = Config(fileName).getContent(configName) super(ThemisPool, self).__init__(**self.config) # 創(chuàng)建隊(duì)列作為 池 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)建 初始化連接數(shù) 數(shù)量的連接放入池中 self.pool.put(self.createConn()) # 啟動(dòng)日志 print('\033[1;32m ThemisPool connect database {database}, login is {user} \033[0m'.format(database=self.database, user=self.user)) # 生產(chǎn)連接 def createConn(self): # 使用mysql基本類 # pymysql.connect 參數(shù)這里不做解釋,具體請(qǐng)查閱官網(wǎng) 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() # 如果池中大于初始值就將多余關(guān)閉,否則重新放入池中 if self.pool.qsize() < self.initsize: self.pool.put(conn) self.idleSize += 1 else: try: # 取出多余連接并關(guān)閉 surplus = self.pool.get() surplus.close() del surplus self.idleSize -= 1 except pymysql.ProgrammingError as e: raise e finally: self._lock.release() # 拉取數(shù)據(jù)(查詢) # 可用語(yǔ)句類型 (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) # 更新 # 可用語(yǔ)句類型 (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
所有配置屬性
參數(shù) | 說(shuō)明 | 類型 | 默認(rèn)值 |
---|---|---|---|
host | 主機(jī)地址 | str | localhost |
port | 端口號(hào) | int | 3306 |
user | mysql登錄用戶名 | str | root |
password | mysql登錄密碼 | str | - |
database | 訪問(wèn)庫(kù)名 | str | - |
initsize | 初始化連接數(shù) | int | 3 |
maxsize | 最大連接數(shù) | int | 6 |
開(kāi)始使用
from util.ThemisPool import ThemisPool # 初始化ThemisPool連接池 (Initialize the ThemisPool connection pool) db = ThemisPool() # 查詢拉取數(shù)據(jù),函數(shù)會(huì)直接返回?cái)?shù)據(jù) (Query pull data.It returns data directly) selectSql = "select * from user;" data = db.fetchone(selectSql) # 增、刪、改語(yǔ)句, 如果有使用mysql自增長(zhǎng)插入的值函數(shù)會(huì)返回自增長(zhǎng)的數(shù)據(jù) (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)
自定義配置文件名 & 配置標(biāo)簽
配置文件名默認(rèn)為 db.cnf, 配置標(biāo)簽?zāi)J(rèn)為 [mysql]
例如自定義配置文件名為 myDB.cnf, 配置標(biāo)簽為 [mysqlConfig]
# myDB.cnf [mysqlConfig] host = localhost user = root password = 12345678 database = practice initsize = 3 maxsize = 6
# 使用時(shí) ... db = ThemisPool(fileName='myDB.cnf', configName='mysqlConfig') ...
命名思路
Themis(忒彌斯) 取名來(lái)自于古希臘神話中秩序女神的名字, 就如同連接池的作用一樣, 管理所有用戶的連接, 減少不必要的損耗。
GitHub地址
以上就是本次的全部?jī)?nèi)容, 下版本將會(huì)解決 python 不能對(duì) datetime 類型的數(shù)據(jù)進(jìn)行 json格式化 的問(wèn)題, 并將它集成進(jìn)來(lái)
到此這篇關(guān)于python自制簡(jiǎn)易mysql連接池的實(shí)現(xiàn)示例的文章就介紹到這了,更多相關(guān)python mysql連接池內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
python 對(duì)txt中每行內(nèi)容進(jìn)行批量替換的方法
今天小編就為大家分享一篇python 對(duì)txt中每行內(nèi)容進(jìn)行批量替換的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-07-07python跳過(guò)第一行快速讀取文件內(nèi)容的實(shí)例
今天小編就為大家分享一篇python跳過(guò)第一行快速讀取文件內(nèi)容的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-07-07