8.5-数据库连接池
01 如何在python中操作数据库?
插图:恶搞图15

在后端开发中免不掉与数据库打交道,无非是使用orm或者原生sql来操作数据库。
在python中通过原生sql操作数据库,主流就两种。
- 使用pymysql模块:
pymysql支持python2.x和python3.x的版本 - 使用mysqldb模块:
mysqldb仅支持python2.x的版本
orm的使用以flask和django为例。
- flask使用的orm是基于
SQLAlchemy(SQLAlchemy本就是orm),flask团队并在SQLAlchemy基础之上又封装了一个Flask-SQLchemy并予以应用 。 - django使用的orm是django自带的orm。
orm的操作数据库的方式我们已经熟知了,这里我们聊一聊如何在web中使用原生sql操作数据库,以及会出现的问题。
02 在web中使用原生sql(pymysql)操作数据库?
2.1 在web中通过原生sql操作数据库会出现的问题。

示例1:
把所有的数据库操作全部都放在了视图函数里面。
from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello():
import pymysql
CONN = pymysql.connect(host='127.0.0.1',
port=3306,
user='root',
password='123',
database='pooldb',
charset='utf8')
cursor = CONN.cursor()
cursor.execute('select * from tb1')
result = cursor.fetchall()
cursor.close()
print(result)
return "Hello World"
if __name__ == '__main__':
app.run()
会出现的问题
- 很多个用户并发的来请求,一个用户可以理解为一个线程,每个线程都会跟数据库建立连接,数据库承受不了这种量级的连接数。
示例2
为了避免之前每个用户都建立连接,我们把数据库连接放到了全局变量里面,只会建立一次连接,但是依然会出现问题。
from flask import Flask
app = Flask(__name__)
import pymysql
CONN = pymysql.connect(host='127.0.0.1',
port=3306,
user='root',
password='123',
database='pooldb',
charset='utf8')
@app.route("/")
def hello():
cursor = CONN.cursor()
cursor.execute('select * from tb1')
result = cursor.fetchall()
cursor.close()
print(result)
return "Hello World"
if __name__ == '__main__':
app.run()
会出现的问题:
- 会出现线程安全问题,比如如果第一个用户拿到了连接给关闭了,而第二个用户正在进行查询,第二个用户查询的时候第一个用户把连接断了,会导致第二个用户出现问题。
- 假设第一用户查询了一下表1,正准备获取查询的内容,这时第二个人查询了一下表2,由于cursor对象都是同一个,第一个人获取到的查询内容就是表2的内容了,所以也会出现线程安全问题
示例3
为了避免之前的线程不安全,在示例2的基础上加上一把线程锁
from flask import Flask
import threading
app = Flask(__name__)
import pymysql
CONN = pymysql.connect(host='127.0.0.1',
port=3306,
user='root',
password='123',
database='pooldb',
charset='utf8')
@app.route("/")
def hello():
with threading.Lock():
cursor = CONN.cursor()
cursor.execute('select * from tb1')
result = cursor.fetchall()
cursor.close()
print(result)
return "Hello World"
if __name__ == '__main__':
app.run()
会出现的问题:




