MySQL☞自连接

MySQL☞自连接

自连接:一张表中根据自身列之间的关联关系,自己跟自己链接。

  A、创建一个user表,且插入数据,数据如下:

     

  B、分析: user表看成两张表,一张员工表,一张领导表,发现员工表中lead(领导编号)等于领导表中id工的编号)员工表和领导表中之间的关联关系:       员工表.lead=领导表.id

  案例:

    1、查询user表中员工的编号,姓名,以及领导的编号,姓名

       

    2、查询user表中员工的编号,姓名,职位,以及领导的编号,姓名,职位

       

    3、查询user表中员工的编号,姓名,职位,工资,以及领导的编号,姓名,职位,工资, 最后根据员 工的工资进行升序排列

       

    4、查询工资在3000~6000之间,并且名字中不包含汉字王 的员工的编号,姓名,工资以及领导的编号, 姓名,工资,根据员工的编号进行降序排列。

       

 

posted @ 2018-10-26 12:10 大鑫鑫 阅读( ...) 评论( ...) 编辑 收藏
<think>我们讨论的是在MySQL数据库环境下,如何设计一个符合分层架构的应用程序,特别是数据库连接的管理。 重点:将数据库连接创建放在基础设施层,避免业务层直接创建连接。 我们将设计一个类似之前PostgreSQL示例的结构,但针对MySQL进行调整,并考虑MySQL的特性(如存储引擎、字符集等)。 同时,我们将使用PyMySQLmysqlclient作为驱动(这里使用mysqlclient,因为它性能更好)。 我们将构建以下层次: 1. 基础设施层:负责数据库连接池的管理。 2. 数据访问层(可选)或直接由应用层调用基础设施层的会话管理。 3. 应用层:业务逻辑。 4. 表现层:可以是Web框架(如Flask)或GUI(如PyQt)等。 注意:由于问题中只提到了“mysql”,我们假设是使用MySQL数据库,并且使用SQLAlchemy作为ORM。 我们将按照以下步骤: 1. 创建数据库连接管理器(单例模式),管理连接池。 2. 使用上下文管理器管理会话作用域。 3. 在应用层通过依赖注入使用会话。 4. 示例一个简单的业务逻辑(比如用户管理)。 另外,针对MySQL的一些特性,我们需要注意: - 连接字符串:mysql+pymysql://user:password@localhost/dbname 或 mysql+mysqldb://... - 设置字符集:通常使用utf8mb4以支持完整的Unicode(包括表情符号)。 - 设置存储引擎:InnoDB(支持事务)。 下面是一个针对MySQL的完整示例:</think>以下是为 MySQL 数据库设计的专业架构方案,严格遵循分层架构原则和最佳实践: ### MySQL 数据库分层架构实现 ```python import os from contextlib import contextmanager from typing import Iterator from sqlalchemy import create_engine, text from sqlalchemy.orm import sessionmaker, scoped_session import mysql.connector.pooling # 直接使用MySQL官方连接池 # 1. 基础设施层 - MySQL连接管理器 class MySQLConnectionManager: """MySQL连接池管理器(线程安全)""" _pool = None @classmethod def initialize_pool(cls, **config): """初始化连接池""" if cls._pool is None: # 默认配置 default_config = { 'pool_name': 'mysql_pool', 'pool_size': 10, 'host': 'localhost', 'user': 'root', 'password': '', 'database': 'app_db', 'charset': 'utf8mb4', 'autocommit': False, 'pool_reset_session': True } default_config.update(config) cls._pool = mysql.connector.pooling.MySQLConnectionPool(**default_config) @classmethod @contextmanager def connection_scope(cls) -> Iterator: """提供MySQL连接上下文""" if cls._pool is None: raise RuntimeError("连接池未初始化") conn = cls._pool.get_connection() try: yield conn conn.commit() except Exception as e: conn.rollback() raise e finally: conn.close() @classmethod def close_pool(cls): """关闭连接池""" if cls._pool: cls._pool._remove_connections() # 关闭所有连接 cls._pool = None # 2. SQLAlchemy集成层 class SQLAlchemyManager: """SQLAlchemy ORM管理器""" _engine = None _session_factory = None @classmethod def initialize(cls, connection_string: str, **kwargs): """初始化SQLAlchemy引擎""" if cls._engine is None: # MySQL特定配置 pool_options = { 'pool_size': 10, 'max_overflow': 20, 'pool_recycle': 3600, 'pool_pre_ping': True } pool_options.update(kwargs.get('pool_options', {})) # 创建引擎 cls._engine = create_engine( connection_string, **pool_options ) cls._session_factory = sessionmaker( bind=cls._engine, autocommit=False, autoflush=False ) @classmethod @contextmanager def session_scope(cls) -> Iterator: """提供SQLAlchemy会话上下文""" if cls._session_factory is None: raise RuntimeError("SQLAlchemy未初始化") session = scoped_session(cls._session_factory)() try: yield session session.commit() except Exception as e: session.rollback() raise e finally: session.close() @classmethod def get_engine(cls): return cls._engine # 3. 配置管理 class DBConfig: """数据库配置管理""" @staticmethod def get_mysql_config(): """从环境变量获取MySQL配置""" return { 'host': os.getenv('MYSQL_HOST', 'localhost'), 'port': int(os.getenv('MYSQL_PORT', 3306)), 'user': os.getenv('MYSQL_USER', 'root'), 'password': os.getenv('MYSQL_PASSWORD', ''), 'database': os.getenv('MYSQL_DATABASE', 'app_db'), 'charset': os.getenv('MYSQL_CHARSET', 'utf8mb4') } @staticmethod def get_sqlalchemy_url(): """生成SQLAlchemy连接字符串""" config = DBConfig.get_mysql_config() return f"mysql+mysqlconnector://{config['user']}:{config['password']}@{config['host']}:{config['port']}/{config['database']}?charset={config['charset']}" # 4. 数据访问层 class UserRepository: """用户数据访问对象""" def __init__(self): # 延迟初始化连接 pass def get_user_by_id(self, user_id: int): """使用原生MySQL连接查询""" with MySQLConnectionManager.connection_scope() as conn: cursor = conn.cursor(dictionary=True) cursor.execute("SELECT * FROM users WHERE id = %s", (user_id,)) return cursor.fetchone() def get_users_with_orm(self, page: int = 1, per_page: int = 10): """使用SQLAlchemy ORM查询""" from models import User # 假设有User模型 with SQLAlchemyManager.session_scope() as session: offset = (page - 1) * per_page return session.query(User).offset(offset).limit(per_page).all() # 5. 应用启动与关闭 def initialize_database(): """应用启动时初始化数据库连接""" # 初始化原生MySQL连接池 MySQLConnectionManager.initialize_pool(**DBConfig.get_mysql_config()) # 初始化SQLAlchemy SQLAlchemyManager.initialize(DBConfig.get_sqlalchemy_url()) # 执行数据库迁移(示例) with SQLAlchemyManager.session_scope() as session: # 检查表是否存在 result = session.execute(text("SHOW TABLES LIKE 'users'")) if not result.fetchone(): # 执行DDL创建表 session.execute(text(""" CREATE TABLE users ( id INT AUTO_INCREMENT PRIMARY KEY, username VARCHAR(50) NOT NULL UNIQUE, email VARCHAR(100) NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 """)) session.commit() def shutdown_database(): """应用关闭时清理资源""" MySQLConnectionManager.close_pool() engine = SQLAlchemyManager.get_engine() if engine: engine.dispose() # 6. 使用示例(Web应用) from flask import Flask, jsonify app = Flask(__name__) @app.before_first_request def before_first_request(): initialize_database() @app.route('/users/<int:user_id>') def get_user(user_id): repo = UserRepository() user = repo.get_user_by_id(user_id) return jsonify(user) if user else ('Not found', 404) @app.teardown_appcontext def teardown_db(exception=None): shutdown_database() if __name__ == '__main__': app.run() ``` ### MySQL 特定优化策略 1. **连接池配置优化**: ```python # 根据负载动态调整连接池大小 def dynamic_pool_adjustment(): import threading import time import psutil while True: cpu_percent = psutil.cpu_percent() mem_available = psutil.virtual_memory().available # 根据系统负载调整连接池大小 if cpu_percent < 30 and mem_available > 2 * 1024**3: # 2GB可用内存 new_size = min(MySQLConnectionManager._pool.pool_size + 5, 100) else: new_size = max(MySQLConnectionManager._pool.pool_size - 2, 5) MySQLConnectionManager._pool.set_config(pool_size=new_size) time.sleep(60) # 每分钟检查一次 # 启动后台线程 threading.Thread(target=dynamic_pool_adjustment, daemon=True).start() ``` 2. **查询性能优化**: ```python # 使用MySQL的EXPLAIN分析查询性能 class QueryOptimizer: @staticmethod def analyze_query(query: str, params=None): with MySQLConnectionManager.connection_scope() as conn: cursor = conn.cursor() cursor.execute(f"EXPLAIN {query}", params or ()) return cursor.fetchall() # 使用示例 optimizer = QueryOptimizer() analysis = optimizer.analyze_query("SELECT * FROM users WHERE username = %s", ('john',)) ``` 3. **读写分离实现**: ```python class MySQLRouter: """MySQL读写分离路由器""" def __init__(self): self.read_pool = None self.write_pool = None def initialize(self, read_config, write_config): self.read_pool = mysql.connector.pooling.MySQLConnectionPool(**read_config) self.write_pool = mysql.connector.pooling.MySQLConnectionPool(**write_config) @contextmanager def connection_scope(self, read_only=False): pool = self.read_pool if read_only else self.write_pool conn = pool.get_connection() try: yield conn if not read_only: conn.commit() except Exception: if not read_only: conn.rollback() raise finally: conn.close() # 在业务层使用 router = MySQLRouter() router.initialize(read_config, write_config) # 读操作 with router.connection_scope(read_only=True) as conn: cursor = conn.cursor() cursor.execute("SELECT * FROM users") # 写操作 with router.connection_scope() as conn: cursor = conn.cursor() cursor.execute("INSERT INTO users (...) VALUES (...)") ``` 4. **备份与恢复机制**: ```python class MySQLBackup: """MySQL数据库备份工具""" def __init__(self, config): self.config = config def full_backup(self, output_path): """执行全量备份""" import subprocess cmd = [ 'mysqldump', '--single-transaction', '--routines', '--triggers', '--events', '-h', self.config['host'], '-u', self.config['user'], f"-p{self.config['password']}", self.config['database'], '--result-file', output_path ] subprocess.run(cmd, check=True) def point_in_time_recovery(self, binlog_file, binlog_pos): """执行时间点恢复""" # 实现基于binlog的精确恢复 pass ``` ### MySQL 最佳实践 1. **连接参数优化**: ```python # 推荐连接字符串参数 connection_string = ( "mysql+mysqlconnector://" "user:password@host:port/db" "?charset=utf8mb4" "&connect_timeout=10" "&read_timeout=30" "&write_timeout=20" "&pool_size=10" "&max_overflow=20" ) ``` 2. **索引优化策略**: ```sql -- 使用覆盖索引 CREATE INDEX idx_user_email ON users(email) INCLUDE (username, created_at); -- 使用全文索引 ALTER TABLE products ADD FULLTEXT(name, description); ``` 3. **事务隔离级别**: ```python # 在关键业务中设置事务隔离级别 with SQLAlchemyManager.session_scope() as session: session.execute(text("SET TRANSACTION ISOLATION LEVEL READ COMMITTED")) # 业务操作 ``` 4. **监控与诊断**: ```python class MySQLMonitor: """MySQL性能监控""" def get_status(self): with MySQLConnectionManager.connection_scope() as conn: cursor = conn.cursor(dictionary=True) cursor.execute("SHOW GLOBAL STATUS") return {row['Variable_name']: row['Value'] for row in cursor} def get_variables(self): with MySQLConnectionManager.connection_scope() as conn: cursor = conn.cursor(dictionary=True) cursor.execute("SHOW GLOBAL VARIABLES") return {row['Variable_name']: row['Value'] for row in cursor} def get_processlist(self): with MySQLConnectionManager.connection_scope() as conn: cursor = conn.cursor(dictionary=True) cursor.execute("SHOW FULL PROCESSLIST") return cursor.fetchall() ``` ### 架构优势 1. **双连接池策略**: - 原生连接池:高性能简单查询 - SQLAlchemy连接池:ORM复杂操作 2. **MySQL特性支持**: - 完整支持存储引擎(InnoDB/MyISAM) - 字符集与排序规则管理 - 事务与锁机制优化 3. **弹性扩展能力**: ```mermaid graph LR A[应用] --> B[读写分离] B --> C[主库集群] B --> D[从库集群] C --> E[分片1] C --> F[分片2] D --> G[分片1副本] D --> H[分片2副本] ``` 4. **全生命周期管理**: - 启动时自动初始化 - 运行时动态调整 - 关闭时优雅释放
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值