conn_mysql.py 3.5 KB

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