 other
other
  # 基本用法

1000客户端并发来 要创建1000个数据库连接吗?创建连接后再回来断掉,下一次又需要再次创建连接?
<1>个数问题 <2>连接后断开再连接消耗内存等资源的问题.需要一个东西控制网站最多连接数据库的数量,够了后来者就排队;
创建连接后不用此连接了但不断开暂时存起来,以便连接的重用.
解决方案: 使用数据库连接池.
pip3.9 install pymysql
pip3.9 install dbutils
1
2
2
import threading
import pymysql
from dbutils.pooled_db import PooledDB
MYSQL_DB_POOL = PooledDB(
    creator=pymysql,  # -- 使用链接数据库的模块
    maxconnections=10,  # -- 连接池允许的最大连接数,0和None表示不限制连接数
    # -- 初始化时/程序运行时,链接池中至少创建的空闲的链接,0表示不创建
    #    最开始的时候没有那么多请求的到来,没必要在内部创建10个连接 "10是上面maxconnections的值"
    #    所以最小创建连接数,最开始的时候创建两个,等着用,后面不够用了,再自动去增加.
    mincached=2,
    # -- 链接池中最多闲置的链接,0和None不限制
    #    一开始连接池有两个连接,突然用户猛增连接池满了,过了一会用户量又少了,那么过段时间就要对其进行回收.
    maxcached=5,
    # -- 该参数值无论设置为多少,生效的只会是0! 不用设置!
    #    连接池中最多共享的连接数量.0和None表示全部共享!
    maxshared=3,
    # -- 连接池中如果没有可用连接,是否阻塞等待. True等待、False不等待然后报错.
    #    eg: 同时来11个人,有个人就得等.. 因为maxconnections=10
    blocking=True,
    # -- 一个连接最多被重复使用的次数. None表示无限制! 一般都设置为None!
    maxusage=None,
    # -- 开始会话(连接)前执行的命令列表. 如: ["set datestyle to ...", "set time zone ..."]
    setsession=[],
    # -- 使用连接前先ping下MySQL服务端,检查mysql服务是否可用 该参数值通常设置为0
    #    0 = None = never 不用ping; 1 = default = whenever it is requested 当用连接时ping
    #    2 = when a cursor is created; 4 = when a query is executed ; 7 = always
    ping=0,
    host='127.0.0.1',
    port=3306,
    user='root',
    password='123456',
    database='youku',
    charset='utf8'
)
def task():
    conn = MYSQL_DB_POOL.connection()  # -- 去连接池获取一个连接
    print("该链接被拿走了!", conn._con)
    print("池子里目前有这些链接:", MYSQL_DB_POOL._idle_cache, '\r\n')
    cursor = conn.cursor(pymysql.cursors.DictCursor)
    cursor.execute('select * from user')
    result = cursor.fetchall()
    cursor.close()
    # -- 并不是关闭连接 而是将连接交还给数据库连接池
    conn.close()
def run():
    for i in range(10):
        t = threading.Thread(target=task)
        t.start()
if __name__ == '__main__':
    run()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# SQL工具类
基于数据库连接池开发一个公共的SQL操作类, 方便以后操作数据库.
# 单例和方法
# db.py
import pymysql
from dbutils.pooled_db import PooledDB
# 这个类中集成了所有的数据库连接池和pymysql数据的操作
class DBHelper(object):
    def __init__(self):
        # TODO 此处配置,可以去配置文件中读取。
        self.pool = PooledDB(
            creator=pymysql,  
            maxconnections=5,  
            mincached=2,  
            maxcached=3,
            blocking=True, 
            setsession=[], 
            ping=0,
            host='127.0.0.1',
            port=3306,
            user='root',
            password='root123',
            database='userdb',
            charset='utf8'
        )
    def get_conn_cursor(self):
        conn = self.pool.connection()
        cursor = conn.cursor(pymysql.cursors.DictCursor)
        return conn, cursor
    def close_conn_cursor(self, *args):
        for item in args:
            item.close()
    def exec(self, sql, **kwargs):
        conn, cursor = self.get_conn_cursor()
        cursor.execute(sql, kwargs)
        conn.commit()
        self.close_conn_cursor(conn, cursor)
    def fetch_one(self, sql, **kwargs):
        conn, cursor = self.get_conn_cursor()
        cursor.execute(sql, kwargs)
        result = cursor.fetchone()
        self.close_conn_cursor(conn, cursor)
        return result
    def fetch_all(self, sql, **kwargs):
        conn, cursor = self.get_conn_cursor()
        cursor.execute(sql, kwargs)
        result = cursor.fetchall()
        self.close_conn_cursor(conn, cursor)
        return result
db = DBHelper()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# other.py 导入db这一个对象(它是单例模式实现的)
from db import db
db.exec("insert into d1(name) values(%(name)s)", name="武沛齐666")
ret = db.fetch_one("select * from d1")
print(ret)
ret = db.fetch_one("select * from d1 where id=%(nid)s", nid=3)
print(ret)
ret = db.fetch_all("select * from d1")
print(ret)
ret = db.fetch_all("select * from d1 where id>%(nid)s", nid=2)
print(ret)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 上下文管理
如果你想要让他也支持 with 上下文管理.
with 获取连接:
	执行SQL(执行完毕后,自动将连接交还给连接池)
1
2
2
# db_context.py
import threading
import pymysql
from dbutils.pooled_db import PooledDB
# 全局变量
POOL = PooledDB(
    creator=pymysql, 
    maxconnections=5, 
    mincached=2, 
    maxcached=3,
    blocking=True,  
    setsession=[], 
    ping=0,
    host='127.0.0.1',
    port=3306,
    user='root',
    password='root123',
    database='userdb',
    charset='utf8'
)
class Connect(object):
    def __init__(self):
        self.conn = conn = POOL.connection()
        self.cursor = conn.cursor(pymysql.cursors.DictCursor)
    def __enter__(self):
        return self
    def __exit__(self, exc_type, exc_val, exc_tb):
        self.cursor.close()
        self.conn.close()
    def exec(self, sql, **kwargs):
        self.cursor.execute(sql, kwargs)
        self.conn.commit()
    def fetch_one(self, sql, **kwargs):
        self.cursor.execute(sql, kwargs)
        result = self.cursor.fetchone()
        return result
    def fetch_all(self, sql, **kwargs):
        self.cursor.execute(sql, kwargs)
        result = self.cursor.fetchall()
        return result
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
from db_context import Connect
# 有一个好处 在同一个连接下可以执行多个sql语句
with Connect() as obj:
    # print(obj.conn)
    # print(obj.cursor)
    ret = obj.fetch_one("select * from d1")
    print(ret)
    ret = obj.fetch_one("select * from d1 where id=%(id)s", id=3)
    print(ret)
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
