| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175 |
- import os
- import pymysql
- import threading
- import time
- import atexit
- from collections import deque
- # simple direct connector (used by some scripts)
- from pymysql.cursors import DictCursor
- def get_connection():
- return pymysql.connect(
- host="120.24.26.108",
- port=3307,
- user="root",
- password="zhijiayun123456",
- database="drug_retrieve",
- charset="utf8mb4",
- autocommit=False,
- cursorclass=DictCursor,
- )
- # connection pool used by a_mt.py
- MYSQL_POOL = None
- class PooledConnection:
- def __init__(self, conn, pool):
- self._conn = conn
- self._pool = pool
- self._closed = False
- def cursor(self, *args, **kwargs):
- return self._conn.cursor(*args, **kwargs)
- def commit(self):
- return self._conn.commit()
- def rollback(self):
- return self._conn.rollback()
- def ping(self, *args, **kwargs):
- return self._conn.ping(*args, **kwargs)
- def close(self):
- if self._closed:
- return
- self._closed = True
- try:
- self._pool.putconn(self._conn)
- except Exception:
- try:
- self._conn.close()
- except Exception:
- pass
- def __getattr__(self, item):
- return getattr(self._conn, item)
- class MySQLConnectionPool:
- def __init__(self, minconn=1, maxconn=10, **connect_kwargs):
- self.minconn = int(minconn)
- self.maxconn = int(maxconn)
- self.connect_kwargs = dict(connect_kwargs)
- self._lock = threading.Lock()
- self._pool = deque()
- self._total = 0
- for _ in range(self.minconn):
- conn = pymysql.connect(**self.connect_kwargs)
- self._pool.append(conn)
- self._total += 1
- def getconn(self, timeout=None):
- start = time.time()
- while True:
- conn = None
- with self._lock:
- if self._pool:
- conn = self._pool.popleft()
- elif self._total < self.maxconn:
- conn = pymysql.connect(**self.connect_kwargs)
- self._total += 1
- if conn is None:
- if timeout is not None and (time.time() - start) >= timeout:
- raise TimeoutError("获取数据库连接超时")
- time.sleep(0.05)
- continue
- # 尝试 ping 确认连接有效,若无效则关闭并尝试重建
- try:
- conn.ping(reconnect=True)
- return PooledConnection(conn, self)
- except Exception:
- try:
- conn.close()
- except Exception:
- pass
- with self._lock:
- self._total = max(0, self._total - 1)
- # 尝试新建连接并返回
- try:
- new_conn = pymysql.connect(**self.connect_kwargs)
- with self._lock:
- self._total += 1
- return PooledConnection(new_conn, self)
- except Exception:
- # 若重建失败且超时则抛出,否则继续重试
- if timeout is not None and (time.time() - start) >= timeout:
- raise TimeoutError("获取数据库连接超时(重建失败)")
- time.sleep(0.1)
- continue
- def putconn(self, conn):
- try:
- conn.ping(reconnect=True)
- with self._lock:
- self._pool.append(conn)
- except Exception:
- try:
- conn.close()
- except Exception:
- pass
- with self._lock:
- self._total = max(0, self._total - 1)
- def closeall(self):
- with self._lock:
- while self._pool:
- c = self._pool.popleft()
- try:
- c.close()
- except Exception:
- pass
- self._total = 0
- def get_mysql():
- global MYSQL_POOL
- if 'MYSQL_POOL' not in globals() or MYSQL_POOL is None:
- MYSQL_POOL = None
- try:
- MYSQL_POOL = MySQLConnectionPool(
- minconn=1,
- maxconn=20,
- host="120.24.26.108",
- port=3307,
- user="root",
- password="zhijiayun123456",
- database="drug_retrieve",
- charset="utf8mb4",
- cursorclass=pymysql.cursors.Cursor,
- )
- except Exception:
- MYSQL_POOL = None
- if MYSQL_POOL is None:
- return pymysql.connect(
- host="120.24.26.108",
- port=3307,
- user="root",
- password="zhijiayun123456",
- database="drug_retrieve",
- charset="utf8mb4",
- cursorclass=pymysql.cursors.Cursor,
- )
- return MYSQL_POOL.getconn()
- # 在程序退出时确保池中所有物理连接被关闭
- try:
- atexit.register(lambda: MYSQL_POOL.closeall() if 'MYSQL_POOL' in globals() and MYSQL_POOL is not None else None)
- except Exception:
- pass
|