import mysql.connector from mysql.connector import errorcode from .config import settings from app.core.logger import get_logger logger = get_logger(__name__) # 全局的连接池 db_connection_pool = None def init_database(): """ 初始化数据库:如果数据库或表不存在,则创建它们。 """ logger.info("--- 开始初始化数据库 ---") # 1. 尝试连接MySQL服务器(不指定数据库) try: cnx = mysql.connector.connect(**settings.DATABASE_CONFIG) cursor = cnx.cursor() # 2. 创建数据库(如果不存在) cursor.execute(f"CREATE DATABASE IF NOT EXISTS {settings.DB_NAME} DEFAULT CHARACTER SET 'utf8mb4'") logger.info(f"数据库 '{settings.DB_NAME}' 已准备就绪。") # 3. 切换到目标数据库 cnx.database = settings.DB_NAME # 4. 创建表(如果不存在) table_description = ( f"CREATE TABLE IF NOT EXISTS `{settings.DB_TABLE_NAME}` (" " `img_id` INT AUTO_INCREMENT PRIMARY KEY," " `img_name` VARCHAR(255) NULL," " `img_path` VARCHAR(512) NOT NULL," " `img_result_json` JSON NOT NULL," " `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP" ") ENGINE=InnoDB" ) cursor.execute(table_description) logger.info(f"数据表 '{settings.DB_TABLE_NAME}' 已准备就绪。") except mysql.connector.Error as err: logger.error(f"数据库初始化失败: {err}") exit(1) # 初始化失败直接退出程序 finally: if 'cursor' in locals() and cursor: cursor.close() if 'cnx' in locals() and cnx.is_connected(): cnx.close() logger.info("--- 数据库初始化完成 ---") def load_database_pool(): """ 在应用启动时创建数据库连接池。 """ global db_connection_pool if db_connection_pool is None: logger.info("--- 创建数据库连接池 ---") try: db_connection_pool = mysql.connector.pooling.MySQLConnectionPool( pool_name="mypool", pool_size=5, # 池中保持的连接数 **settings.DATABASE_CONFIG_WITH_DB ) logger.info("--- 数据库连接池创建成功 ---") except mysql.connector.Error as err: logger.error(f"创建数据库连接池失败: {err}") exit(1) def close_database_pool(): """ 在应用关闭时,不需要手动关闭连接池,连接器会自动处理。 这个函数留作备用。 """ logger.info("--- 数据库连接池将自动关闭 ---") # --- FastAPI 依赖注入 --- def get_db_connection(): """ 一个FastAPI依赖项,用于从池中获取数据库连接。 它确保连接在使用后返回到池中。 """ if db_connection_pool is None: raise RuntimeError("数据库连接池未初始化") db_conn = None try: db_conn = db_connection_pool.get_connection() yield db_conn except mysql.connector.Error as err: logger.error(f"获取数据库连接失败: {err}") # 这里可以根据需要抛出HTTPException finally: if db_conn and db_conn.is_connected(): db_conn.close()