conn_mysql.py 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. import logging
  2. from commons.config import (
  3. MYSQL_HOST,
  4. MYSQL_PORT,
  5. MYSQL_USER,
  6. MYSQL_PASSWORD,
  7. MYSQL_DATABASE,
  8. MYSQL_POOL_MAXCONNECTIONS,
  9. MYSQL_POOL_MIN_CACHED,
  10. MYSQL_POOL_MAX_CACHED,
  11. )
  12. import os
  13. import pymysql
  14. from dbutils.pooled_db import PooledDB
  15. from pymysql.cursors import DictCursor
  16. logger = logging.getLogger(__name__)
  17. # 连接池公共参数(可自行调大 maxconnections 等)
  18. _POOL_COMMON = {
  19. "maxconnections": MYSQL_POOL_MAXCONNECTIONS,
  20. "mincached": MYSQL_POOL_MIN_CACHED,
  21. "maxcached": MYSQL_POOL_MAX_CACHED,
  22. "blocking": True,
  23. }
  24. def _create_pool(
  25. host,
  26. port,
  27. user,
  28. password,
  29. database,
  30. ):
  31. return PooledDB(
  32. creator=pymysql,
  33. cursorclass=DictCursor,
  34. charset="utf8mb4",
  35. host=host,
  36. port=port,
  37. user=user,
  38. password=password,
  39. database=database,
  40. **_POOL_COMMON,
  41. )
  42. class _MySQLPoolBase:
  43. """共用的取连接、写库、读库逻辑,避免两套类复制粘贴。"""
  44. def __init__(self, pool):
  45. self.pool = pool
  46. def get_conn(self):
  47. return self.pool.connection()
  48. def _close(self, conn, cursor) -> None:
  49. try:
  50. if cursor:
  51. cursor.close()
  52. finally:
  53. if conn:
  54. conn.close()
  55. def _write(self, fn, *args, **kwargs):
  56. conn = self.get_conn()
  57. cursor = conn.cursor()
  58. try:
  59. result = fn(cursor, *args, **kwargs)
  60. conn.commit()
  61. return result
  62. except Exception as e:
  63. logger.error("SQL 执行错误: %s", e)
  64. conn.rollback()
  65. return None
  66. finally:
  67. self._close(conn, cursor)
  68. def execute_many(self, sql, data):
  69. rows = list(data)
  70. if not rows:
  71. return
  72. def _do(c, s, d):
  73. c.executemany(s, d)
  74. self._write(_do, sql, rows)
  75. def execute_one(self, sql, data):
  76. def _do(c, s, d):
  77. c.execute(s, d)
  78. self._write(_do, sql, data)
  79. def update_data(self, sql, data):
  80. self.execute_one(sql, data)
  81. def select_data(self, sql, data=None):
  82. """只读查询,不应 commit。"""
  83. conn = self.get_conn()
  84. cursor = conn.cursor()
  85. try:
  86. if data is not None:
  87. cursor.execute(sql, data)
  88. return cursor.fetchall()
  89. else:
  90. cursor.execute(sql)
  91. return cursor.fetchall()
  92. except Exception as e:
  93. logger.error("SQL 查询错误: %s", e)
  94. return []
  95. finally:
  96. self._close(conn, cursor)
  97. def execute(self, sql, data=None):
  98. """通用写操作,返回受影响行数;失败返回 0。"""
  99. def _do(c, s, d):
  100. if d is not None:
  101. return c.execute(s, d)
  102. return c.execute(s)
  103. result = self._write(_do, sql, data)
  104. return result if isinstance(result, int) else 0
  105. class MySQLPoolOn2(_MySQLPoolBase):
  106. """drug_retrieve_test 库。"""
  107. def __init__(self):
  108. pool = _create_pool(
  109. host=os.environ.get("MYSQL_DRUG_HOST", MYSQL_HOST),
  110. port=int(os.environ.get("MYSQL_DRUG_PORT", str(MYSQL_PORT))),
  111. user=os.environ.get("MYSQL_DRUG_USER", MYSQL_USER),
  112. password=os.environ.get("MYSQL_DRUG_PASSWORD", MYSQL_PASSWORD),
  113. database=os.environ.get("MYSQL_DRUG_DB", MYSQL_DATABASE),
  114. )
  115. super().__init__(pool)
  116. if __name__ == "__main__":
  117. pool = MySQLPoolOn2()
  118. rows = pool.select_data("SELECT 1 AS one")
  119. print(rows)