pool.py 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. """
  4. 数据库连接池
  5. 支持 MySQL、Doris、PostgreSQL
  6. """
  7. import pymysql
  8. import pymysql.cursors
  9. from typing import Any, Optional, Dict
  10. from dbutils.pooled_db import PooledDB
  11. from config import get_config
  12. class DBPool:
  13. """数据库连接池管理器"""
  14. _pools: Dict[str, PooledDB] = {}
  15. @classmethod
  16. def get_pool(cls, db_type: str) -> PooledDB:
  17. """
  18. 获取指定类型的连接池
  19. Args:
  20. db_type: 数据库类型 (mysql/doris/pgsql)
  21. Returns:
  22. 连接池实例
  23. Raises:
  24. ValueError: 不支持的数据库类型
  25. """
  26. if db_type in cls._pools:
  27. return cls._pools[db_type]
  28. cfg: Dict[str, Any] = get_config(f"database.{db_type}", {})
  29. if not cfg:
  30. raise ValueError(f"未配置数据库: {db_type}")
  31. pool_size: int = cfg.get("pool_size", 10)
  32. if db_type == "mysql":
  33. pool = cls._create_mysql_pool(cfg, pool_size)
  34. elif db_type == "doris":
  35. pool = cls._create_doris_pool(cfg, pool_size)
  36. elif db_type == "pgsql":
  37. pool = cls._create_pgsql_pool(cfg, pool_size)
  38. else:
  39. raise ValueError(f"不支持的数据库类型: {db_type}")
  40. cls._pools[db_type] = pool
  41. return pool
  42. @classmethod
  43. def _create_mysql_pool(cls, cfg: Dict[str, Any], pool_size: int) -> PooledDB:
  44. """创建 MySQL 连接池"""
  45. return PooledDB(
  46. creator=pymysql,
  47. maxconnections=pool_size,
  48. mincached=2,
  49. maxcached=pool_size,
  50. blocking=True,
  51. ping=1,
  52. host=str(cfg.get("host", "")),
  53. port=int(cfg.get("port", 3306)),
  54. user=str(cfg.get("user", "")),
  55. password=str(cfg.get("password", "")),
  56. database=str(cfg.get("database", "")),
  57. charset=str(cfg.get("charset", "utf8mb4")),
  58. cursorclass=pymysql.cursors.DictCursor,
  59. )
  60. @classmethod
  61. def _create_doris_pool(cls, cfg: Dict[str, Any], pool_size: int) -> PooledDB:
  62. """创建 Doris 连接池 (使用 MySQL 协议)"""
  63. return PooledDB(
  64. creator=pymysql,
  65. maxconnections=pool_size,
  66. mincached=2,
  67. maxcached=pool_size,
  68. blocking=True,
  69. ping=1,
  70. host=str(cfg.get("host", "")),
  71. port=int(cfg.get("port", 9030)),
  72. user=str(cfg.get("user", "")),
  73. password=str(cfg.get("password", "")),
  74. database=str(cfg.get("database", "")),
  75. charset=str(cfg.get("charset", "utf8mb4")),
  76. cursorclass=pymysql.cursors.DictCursor,
  77. )
  78. @classmethod
  79. def _create_pgsql_pool(cls, cfg: Dict[str, Any], pool_size: int) -> PooledDB:
  80. """创建 PostgreSQL 连接池"""
  81. try:
  82. import psycopg2
  83. import psycopg2.pool
  84. except ImportError:
  85. raise ImportError("需要安装 psycopg2: pip install psycopg2-binary")
  86. return PooledDB(
  87. creator=psycopg2,
  88. maxconnections=pool_size,
  89. mincached=2,
  90. maxcached=pool_size,
  91. blocking=True,
  92. host=str(cfg.get("host", "")),
  93. port=int(cfg.get("port", 5432)),
  94. user=str(cfg.get("user", "")),
  95. password=str(cfg.get("password", "")),
  96. database=str(cfg.get("database", "")),
  97. )
  98. @classmethod
  99. def close_all(cls) -> None:
  100. """关闭所有连接池"""
  101. for pool in cls._pools.values():
  102. try:
  103. pool.close()
  104. except Exception:
  105. pass
  106. cls._pools.clear()
  107. def get_connection(db_type: str):
  108. """
  109. 获取数据库连接
  110. Args:
  111. db_type: 数据库类型 (mysql/doris/pgsql)
  112. Returns:
  113. 数据库连接对象
  114. """
  115. return DBPool.get_pool(db_type).connection()
  116. def get_mysql_conn():
  117. """获取 MySQL 连接(兼容旧API)"""
  118. return get_connection("mysql")
  119. def get_doris_conn():
  120. """获取 Doris 连接(兼容旧API)"""
  121. return get_connection("doris")
  122. def get_pgsql_conn():
  123. """获取 PostgreSQL 连接"""
  124. return get_connection("pgsql")