news 2026/9/13 7:42:38

PyMySQL:Python操作MySQL的首选方案与最佳实践

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
PyMySQL:Python操作MySQL的首选方案与最佳实践

1. 为什么选择PyMySQL作为Python操作MySQL的首选

在Python生态中操作MySQL数据库,开发者通常会面临几个主流选择:MySQL官方提供的mysql-connector-python、老牌的MySQLdb(Python 2时代的主流选择)、以及本文要重点介绍的PyMySQL。经过多年实战检验,PyMySQL已经成为大多数Python开发者连接MySQL数据库的首选方案。

PyMySQL之所以能从众多候选方案中脱颖而出,主要基于以下几个关键优势:

  1. 纯Python实现:PyMySQL完全用Python编写,不依赖任何C扩展。这意味着它在各种操作系统和Python环境中都能无缝运行,避免了编译安装的麻烦。相比之下,MySQLdb需要C编译器支持,在Windows等平台上安装时经常遇到环境配置问题。

  2. Python 3原生支持:PyMySQL从设计之初就专注于Python 3支持,而MySQLdb最初是为Python 2设计的,虽然后来有Python 3移植版,但在兼容性上仍存在一些问题。

  3. 活跃的社区维护:PyMySQL在GitHub上保持着高频更新,issues响应迅速,而MySQLdb的维护相对滞后。根据2023年的统计,PyMySQL在PyPI上的月下载量已经超过MySQLdb三倍以上。

  4. API设计友好:PyMySQL的API设计与Python DB-API 2.0规范高度兼容,对于熟悉Python数据库操作的开发者来说几乎没有学习成本。同时它提供了很多便利的扩展功能。

提示:如果你是从MySQLdb迁移过来的开发者,PyMySQL特意提供了pymysql.install_as_MySQLdb()方法,可以无缝替换原有代码中的MySQLdb引用。

在实际项目选型时,还需要考虑以下技术指标对比:

特性PyMySQLmysql-connector-pythonMySQLdb
Python 3支持⚠️
纯Python实现
连接池支持需扩展
异步支持
性能中等
安装便捷性中等

从实际工程角度考虑,除非你的项目对性能有极端要求(这种情况下可能需要考虑更底层的方案),PyMySQL在开发效率、维护成本和功能完整性上提供了最佳的平衡点。特别是在微服务架构和快速迭代的互联网项目中,PyMySQL的轻量级特性和零配置安装优势更加明显。

2. PyMySQL环境配置与最佳实践

2.1 安装与版本选择策略

PyMySQL的安装非常简单,使用pip即可完成:

pip install pymysql

但对于生产环境,我强烈建议采用以下更稳健的安装方式:

pip install pymysql==1.0.2 --index-url https://pypi.org/simple --trusted-host pypi.org

这里有几个关键考虑:

  1. 显式指定版本号(当前最新稳定版是1.0.2),避免自动升级导致兼容性问题
  2. 使用官方PyPI源确保包完整性
  3. 添加--trusted-host参数避免企业网络环境下的SSL证书问题

注意:PyMySQL 1.0+版本需要Python 3.7+支持。如果你的项目仍在使用Python 3.6或更早版本,应该使用PyMySQL 0.10.x系列。

2.2 连接配置的安全实践

建立数据库连接是任何数据库操作的起点,也是安全风险的高发区域。以下是经过生产环境验证的连接配置方案:

import pymysql def get_secure_connection(): try: connection = pymysql.connect( host='your_mysql_host', user='app_user', password='SuperSecret123!', database='app_db', port=3306, charset='utf8mb4', cursorclass=pymysql.cursors.DictCursor, connect_timeout=5, read_timeout=30, write_timeout=30, ssl={'ca': '/path/to/ca.pem'} # 生产环境必须启用SSL ) return connection except pymysql.MySQLError as e: logger.error(f"Database connection failed: {e}") raise

安全配置要点解析:

  1. 超时设置connect_timeout防止网络问题导致长时间阻塞,read/write_timeout避免慢查询拖垮应用
  2. SSL加密:生产环境必须启用,防止敏感数据在传输过程中被窃听
  3. 字符集:使用utf8mb4而非utf8,确保完整支持emoji等4字节字符
  4. 密码策略:避免在代码中硬编码密码,应该使用环境变量或配置中心

2.3 连接池的高效管理

对于Web应用等高频访问数据库的场景,直接使用短连接会导致严重的性能问题。以下是使用连接池的最佳实践:

from pymysql import pools # 创建连接池 connection_pool = pools.PooledDB( creator=pymysql, mincached=2, maxcached=5, maxconnections=20, blocking=True, **get_secure_connection_params() ) def query_with_pool(sql): conn = connection_pool.connection() try: with conn.cursor() as cursor: cursor.execute(sql) return cursor.fetchall() finally: conn.close()

连接池参数调优建议:

  • mincached:启动时预先创建的闲置连接数
  • maxcached:闲置连接池最大大小
  • maxconnections:池中最大连接数
  • blocking:当连接数达到最大值时是否阻塞等待

根据我们的压力测试结果,对于中等流量的Web应用(约500QPS),推荐配置为mincached=5, maxcached=10, maxconnections=50。但具体数值应该根据实际监控数据进行调整。

3. CRUD操作进阶技巧

3.1 防注入的SQL执行方式

SQL注入是最常见的安全漏洞之一,PyMySQL提供了多种防止注入的机制:

# 危险!绝对避免这种写法 sql = "SELECT * FROM users WHERE username = '" + username + "'" cursor.execute(sql) # 正确做法1:使用参数化查询 sql = "SELECT * FROM users WHERE username = %s" cursor.execute(sql, (username,)) # 正确做法2:使用命名参数 sql = "INSERT INTO users (username, email) VALUES (%(username)s, %(email)s)" cursor.execute(sql, {'username': 'john', 'email': 'john@example.com'})

PyMySQL会对所有参数进行正确的转义处理,确保特殊字符不会被解释为SQL语法。但需要注意,表名和列名不能参数化,必须通过白名单验证:

# 不安全的表名处理 table = request.args.get('table') # 可能被注入 sql = f"SELECT * FROM {table}" # 危险! # 安全做法 valid_tables = {'users', 'products', 'orders'} table = request.args.get('table') if table not in valid_tables: raise ValueError("Invalid table name") sql = f"SELECT * FROM {table}"

3.2 批量操作性能优化

当需要处理大量数据时,单条SQL语句的效率非常低下。PyMySQL提供了高效的批量操作支持:

# 低效的单条插入 for item in items: cursor.execute("INSERT INTO logs (message) VALUES (%s)", (item,)) # 高效的批量插入 sql = "INSERT INTO logs (message) VALUES (%s)" cursor.executemany(sql, [(item,) for item in items])

实测数据显示,对于1000条记录的插入操作:

  • 单条插入耗时约12秒
  • 批量插入仅需0.8秒

但需要注意,executemany在极大量数据(如10万+记录)时可能会耗尽内存。这时应该采用分批次提交的策略:

batch_size = 1000 for i in range(0, len(items), batch_size): batch = items[i:i+batch_size] cursor.executemany(sql, [(item,) for item in batch]) connection.commit() # 分批提交

3.3 事务处理与异常恢复

PyMySQL默认开启自动提交模式,这在生产环境中通常是不可取的。正确的事务处理模式应该是:

try: connection.begin() # 显式开始事务 # 执行多个操作 cursor.execute("UPDATE accounts SET balance = balance - 100 WHERE user_id = 1") cursor.execute("UPDATE accounts SET balance = balance + 100 WHERE user_id = 2") connection.commit() # 提交事务 except Exception as e: connection.rollback() # 发生异常时回滚 logger.error(f"Transaction failed: {e}") raise finally: cursor.close()

事务隔离级别设置(MySQL默认为REPEATABLE READ):

# 设置读已提交隔离级别 cursor.execute("SET TRANSACTION ISOLATION LEVEL READ COMMITTED") connection.commit()

对于分布式系统,还需要考虑长事务带来的锁竞争问题。我们的经验是:

  • 单个事务持续时间不超过500ms
  • 涉及的表行数不超过1000行
  • 避免在事务中进行网络IO操作

4. 高级特性与性能调优

4.1 流式查询处理大结果集

当查询可能返回大量数据时(如导出报表),直接使用fetchall()会导致内存暴涨。PyMySQL提供了流式处理方案:

sql = "SELECT * FROM large_table" cursor = connection.cursor(pymysql.cursors.SSCursor) # 使用服务端游标 try: cursor.execute(sql) for row in cursor: process_row(row) # 逐行处理 finally: cursor.close()

SSCursor(Server Side Cursor)的工作原理是:

  1. 执行查询后,MySQL服务器保持结果集
  2. 客户端每次fetch少量数据(默认1行)
  3. 显著降低内存占用(从GB级降到MB级)

实测对比(查询100万行数据):

  • 普通游标:内存占用1.2GB,耗时15秒
  • SSCursor:内存占用稳定在50MB,耗时18秒

4.2 预处理语句提升性能

对于高频执行的SQL,使用预处理语句(prepared statement)可以显著提升性能:

sql = "SELECT * FROM products WHERE price > %s AND category = %s" prepared_stmt = connection.cursor().execute(sql, (100, 'electronics')) # 后续重复执行时,MySQL会复用执行计划 for params in [(100, 'books'), (200, 'electronics')]: prepared_stmt.execute(params) results = prepared_stmt.fetchall()

性能测试数据(执行1000次):

  • 普通查询:1200ms
  • 预处理语句:800ms

4.3 连接健康检查与重试机制

在网络不稳定的环境中,数据库连接可能会意外中断。健壮的生产代码应该包含连接检查逻辑:

def safe_query(sql, params=None, retries=3): for attempt in range(retries): try: conn = connection_pool.connection() with conn.cursor() as cursor: cursor.execute(sql, params or ()) return cursor.fetchall() except pymysql.OperationalError as e: if attempt == retries - 1: raise time.sleep(2 ** attempt) # 指数退避 finally: conn.close()

重试策略建议:

  • 第一次失败后立即重试(瞬态错误)
  • 第二次等待2秒后重试
  • 第三次等待4秒后重试
  • 超过重试次数后报警

4.4 监控与性能分析

完善的监控是数据库操作不可或缺的部分。推荐采集以下指标:

  1. 查询耗时百分位(P50, P90, P99)
  2. 错误率(按错误类型分类)
  3. 连接池使用率
  4. 慢查询(超过200ms的查询)

使用Prometheus的示例监控代码:

from prometheus_client import Summary, Counter QUERY_TIME = Summary('mysql_query_seconds', 'Time spent executing queries') QUERY_ERRORS = Counter('mysql_query_errors', 'Database query errors', ['error_type']) @QUERY_TIME.time() def monitored_query(sql): try: cursor.execute(sql) return cursor.fetchall() except pymysql.Error as e: QUERY_ERRORS.labels(error_type=type(e).__name__).inc() raise

5. 常见问题排查与解决方案

5.1 连接超时问题分析

错误现象:

pymysql.err.OperationalError: (2013, 'Lost connection to MySQL server during query')

可能原因及解决方案:

  1. 服务器端超时:MySQL的wait_timeout设置过小(默认8小时)

    • 解决方案:SET GLOBAL wait_timeout=28800;(8小时)
  2. 网络不稳定:特别是跨机房访问时

    • 解决方案:增加TCP keepalive设置
    connection = pymysql.connect( ..., read_timeout=30, write_timeout=30, connect_timeout=5, init_command="SET SESSION wait_timeout=28800" )
  3. 查询太复杂:处理大量数据时超时

    • 解决方案:优化查询或分批处理

5.2 字符编码问题处理

典型错误:

pymysql.err.InternalError: (1366, "Incorrect string value: '\\xF0\\x9F\\x98\\x8D' for column")

解决方案:

  1. 确保连接使用utf8mb4字符集:
    connection = pymysql.connect(charset='utf8mb4')
  2. 检查表字段的字符集:
    ALTER TABLE your_table MODIFY your_column VARCHAR(255) CHARACTER SET utf8mb4;
  3. 检查MySQL服务器配置:
    [mysqld] character-set-server=utf8mb4 collation-server=utf8mb4_unicode_ci

5.3 死锁检测与处理

MySQL在发生死锁时会抛出:

pymysql.err.OperationalError: (1213, 'Deadlock found when trying to get lock')

处理策略:

  1. 实现自动重试逻辑:
    max_retries = 3 for attempt in range(max_retries): try: cursor.execute("UPDATE accounts SET balance = balance - 100 WHERE user_id = 1") connection.commit() break except pymysql.err.OperationalError as e: if e.args[0] != 1213 or attempt == max_retries - 1: raise time.sleep(0.1 * (attempt + 1))
  2. 优化事务设计:
    • 缩短事务持续时间
    • 按照固定顺序访问表
    • 避免事务中的用户交互

5.4 连接泄漏排查

连接泄漏会导致连接池耗尽,表现为:

pymysql.err.OperationalError: (1040, 'Too many connections')

诊断方法:

  1. 检查MySQL当前连接:
    SHOW PROCESSLIST;
  2. 使用连接上下文管理器确保释放:
    with connection_pool.connection() as conn: with conn.cursor() as cursor: cursor.execute("SELECT 1")
  3. 在代码中跟踪连接生命周期:
    import weakref connections = set() def tracked_connection(): conn = connection_pool.connection() connections.add(weakref.ref(conn)) return conn

6. PyMySQL与ORM框架的协作

虽然PyMySQL可以直接操作数据库,但在复杂应用中,ORM框架能大幅提高开发效率。以下是PyMySQL与常见ORM的集成方式。

6.1 SQLAlchemy集成

SQLAlchemy是Python最强大的ORM框架之一,使用PyMySQL作为底层驱动:

from sqlalchemy import create_engine # 连接字符串格式: # mysql+pymysql://<username>:<password>@<host>/<dbname>[?<options>] engine = create_engine( 'mysql+pymysql://user:pass@localhost/dbname', pool_size=5, max_overflow=10, pool_timeout=30, pool_recycle=3600, echo=True # 开发时开启SQL日志 )

关键配置参数:

  • pool_size:连接池保持的连接数
  • max_overflow:允许超过pool_size的最大连接数
  • pool_recycle:连接自动回收时间(秒),避免MySQL的wait_timeout断开连接

6.2 Django配置优化

Django默认使用mysqlclient驱动,切换到PyMySQL需要修改settings.py

DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'OPTIONS': { 'driver': 'pymysql', 'host': 'localhost', 'user': 'db_user', 'password': 'db_password', 'database': 'db_name', 'charset': 'utf8mb4', 'init_command': "SET sql_mode='STRICT_TRANS_TABLES'", }, 'CONN_MAX_AGE': 300, # 连接存活时间(秒) 'TEST': { 'CHARSET': 'utf8mb4', 'COLLATION': 'utf8mb4_unicode_ci', } } }

性能优化建议:

  1. 设置CONN_MAX_AGE启用持久连接
  2. 生产环境添加'OPTIONS': {'ssl': {'ca': '/path/to/ca.pem'}}
  3. 测试环境确保使用正确的字符集

6.3 Peewee轻量级ORM集成

Peewee是一个轻量级ORM,与PyMySQL搭配非常适合小型项目:

from peewee import MySQLDatabase db = MySQLDatabase( 'my_database', user='db_user', password='db_password', host='localhost', port=3306, charset='utf8mb4', use_unicode=True, autoconnect=False ) # 使用连接池扩展 from playhouse.pool import PooledMySQLDatabase db = PooledMySQLDatabase( 'my_database', max_connections=8, stale_timeout=300, **{'user': 'db_user', 'password': 'db_password'} )

Peewee+PyMySQL组合的优势:

  • 极低的内存占用(约MySQLdb的1/3)
  • 简单的API设计
  • 内置连接池支持
  • 完善的文档和社区支持

7. 实战案例:电商订单系统设计

让我们通过一个电商订单系统的例子,展示PyMySQL在实际业务中的应用。

7.1 数据库设计

CREATE TABLE `users` ( `id` BIGINT NOT NULL AUTO_INCREMENT, `username` VARCHAR(50) NOT NULL, `balance` DECIMAL(12,2) NOT NULL DEFAULT 0, PRIMARY KEY (`id`), UNIQUE KEY `idx_username` (`username`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; CREATE TABLE `products` ( `id` BIGINT NOT NULL AUTO_INCREMENT, `name` VARCHAR(100) NOT NULL, `price` DECIMAL(10,2) NOT NULL, `stock` INT NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; CREATE TABLE `orders` ( `id` BIGINT NOT NULL AUTO_INCREMENT, `user_id` BIGINT NOT NULL, `status` ENUM('pending','paid','shipped','completed','cancelled') NOT NULL DEFAULT 'pending', `total_amount` DECIMAL(12,2) NOT NULL, `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), KEY `idx_user` (`user_id`), CONSTRAINT `fk_user` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; CREATE TABLE `order_items` ( `id` BIGINT NOT NULL AUTO_INCREMENT, `order_id` BIGINT NOT NULL, `product_id` BIGINT NOT NULL, `quantity` INT NOT NULL, `unit_price` DECIMAL(10,2) NOT NULL, PRIMARY KEY (`id`), KEY `idx_order` (`order_id`), CONSTRAINT `fk_order` FOREIGN KEY (`order_id`) REFERENCES `orders` (`id`), CONSTRAINT `fk_product` FOREIGN KEY (`product_id`) REFERENCES `products` (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

7.2 下单业务实现

def create_order(user_id, items): """ 创建订单的完整事务处理 :param user_id: 用户ID :param items: 商品列表 [{'product_id':1, 'quantity':2}, ...] :return: 订单ID """ conn = get_secure_connection() try: with conn.cursor() as cursor: # 开始事务 conn.begin() # 1. 检查并锁定商品库存 total_amount = 0 for item in items: cursor.execute( "SELECT price, stock FROM products WHERE id = %s FOR UPDATE", (item['product_id'],) ) product = cursor.fetchone() if not product: raise ValueError(f"Product {item['product_id']} not found") if product['stock'] < item['quantity']: raise ValueError(f"Insufficient stock for product {item['product_id']}") total_amount += product['price'] * item['quantity'] # 2. 扣减用户余额 cursor.execute( "UPDATE users SET balance = balance - %s WHERE id = %s AND balance >= %s", (total_amount, user_id, total_amount) ) if cursor.rowcount != 1: raise ValueError("Insufficient balance or user not found") # 3. 创建订单主表 cursor.execute( "INSERT INTO orders (user_id, total_amount) VALUES (%s, %s)", (user_id, total_amount) ) order_id = cursor.lastrowid # 4. 创建订单明细并扣减库存 for item in items: cursor.execute( "INSERT INTO order_items (order_id, product_id, quantity, unit_price) " "VALUES (%s, %s, %s, %s)", (order_id, item['product_id'], item['quantity'], item['price']) ) cursor.execute( "UPDATE products SET stock = stock - %s WHERE id = %s", (item['quantity'], item['product_id']) ) # 提交事务 conn.commit() return order_id except Exception as e: conn.rollback() logger.error(f"Order creation failed: {e}") raise finally: conn.close()

7.3 分页查询优化

电商系统最常见的操作是订单分页查询,以下是经过优化的实现:

def get_user_orders(user_id, page=1, per_page=10): """ 高效的分页查询实现 :return: {'orders': [...], 'total': 100} """ offset = (page - 1) * per_page conn = get_secure_connection() try: with conn.cursor() as cursor: # 使用延迟JOIN优化分页 cursor.execute(""" SELECT o.* FROM ( SELECT id FROM orders WHERE user_id = %s ORDER BY created_at DESC LIMIT %s OFFSET %s ) AS tmp JOIN orders o ON tmp.id = o.id """, (user_id, per_page, offset)) orders = cursor.fetchall() # 获取总数(缓存友好) cursor.execute(""" SELECT COUNT(*) FROM orders WHERE user_id = %s """, (user_id,)) total = cursor.fetchone()[0] return {'orders': orders, 'total': total} finally: conn.close()

这种"延迟JOIN"技术相比直接LIMIT OFFSET有显著性能优势,特别是在大表分页时。测试数据对比(100万订单记录):

  • 传统方式:SELECT * FROM orders LIMIT 10 OFFSET 999990→ 2.3秒
  • 延迟JOIN方式 → 0.15秒

8. 生产环境部署建议

8.1 连接池配置参考

生产环境推荐使用DBUtils或SQLAlchemy的连接池实现:

from dbutils.pooled_db import PooledDB pool = PooledDB( creator=pymysql, mincached=3, maxcached=10, maxconnections=50, blocking=True, ping=1, # 每次借出连接时ping检查 host='mysql-master.example.com', user='app_user', password=os.getenv('DB_PASSWORD'), database='app_db', charset='utf8mb4', cursorclass=pymysql.cursors.DictCursor, ssl={'ca': '/etc/mysql/ca.pem'} )

关键参数说明:

  • ping=1:确保连接从池中取出时是活跃的
  • maxconnections:根据应用服务器CPU核心数设置(建议核心数×5)
  • blocking=True:连接耗尽时等待而非报错

8.2 读写分离实现

对于高负载系统,可以通过PyMySQL实现简单的读写分离:

class MySQLRouter: def __init__(self): self.write_pool = PooledDB(...) # 主库 self.read_pool = PooledDB(...) # 从库 def get_connection(self, read_only=False): return self.read_pool.connection() if read_only else self.write_pool.connection() router = MySQLRouter() # 读操作 with router.get_connection(read_only=True) as conn: conn.cursor().execute("SELECT * FROM products") # 写操作 with router.get_connection() as conn: conn.cursor().execute("INSERT INTO orders ...")

更完善的方案可以结合ProxySQL或MySQL Router实现自动路由。

8.3 慢查询监控与分析

在MySQL配置中开启慢查询日志:

[mysqld] slow_query_log = 1 slow_query_log_file = /var/log/mysql/mysql-slow.log long_query_time = 0.5 log_queries_not_using_indexes = 1

使用pt-query-digest分析慢日志:

pt-query-digest /var/log/mysql/mysql-slow.log > slow_report.txt

对于Python应用,可以通过装饰器自动记录慢查询:

def log_slow_queries(threshold=0.5): def decorator(func): @wraps(func) def wrapper(*args, **kwargs): start = time.time() result = func(*args, **kwargs) duration = time.time() - start if duration > threshold: logger.warning( f"Slow query: {func.__name__} took {duration:.2f}s\n" f"Args: {args}\nSQL: {kwargs.get('sql')}" ) return result return wrapper return decorator

8.4 灾备与故障转移

建议的MySQL高可用架构:

  1. 主从复制:至少1主2从配置
  2. 使用VIP或DNS实现自动故障转移
  3. 应用层重试机制:
def execute_with_retry(sql, params=None, retries=2): for i in range(retries + 1): try: with get_connection() as conn: with conn.cursor() as cursor: cursor.execute(sql, params) return cursor.fetchall() except pymysql.OperationalError as e: if i == retries or e.args[0] not in (2003, 2006, 2013): raise time.sleep(1 * (i + 1)) refresh_connection_pool() # 切换至备用节点

9. PyMySQL的局限性及替代方案

虽然PyMySQL在大多数场景下表现优异,但在某些特殊需求下可能需要考虑替代方案。

9.1 性能敏感场景

当遇到极端性能需求时(如高频交易系统),可以考虑:

  1. mysqlclient:C扩展实现,性能比PyMySQL高约20-30%

    • 安装:pip install mysqlclient
    • 兼容PyMySQL的大部分API
  2. asyncmy:异步IO驱动,适用于asyncio应用

    import asyncmy async def query(): async with asyncmy.connect(...) as conn: async with conn.cursor() as cursor: await cursor.execute("SELECT * FROM users") return await cursor.fetchall()

9.2 特殊数据类型处理

PyMySQL对某些MySQL特殊类型的支持有限:

  1. JSON类型:需要手动转换

    # 写入JSON cursor.execute("INSERT INTO table (json_col) VALUES (%s)", (json.dumps(data),)) # 读取JSON cursor.execute("SELECT json_col FROM table") result = json.loads(cursor.fetchone()['json_col'])
  2. Geometry类型:需要使用mysql-connectorgeoalchemy2等专门库

9.3 多语句执行安全

出于安全考虑,PyMySQL默认禁止多语句执行:

# 默认会报错 cursor.execute("SELECT 1; SELECT 2") # 需要显式启用 connection = pymysql.connect(..., client_flag=pymysql.constants.CLIENT.MULTI_STATEMENTS)

但在生产环境中,建议始终避免多语句执行,防止SQL注入攻击。

10. 持续学习资源推荐

要深入掌握PyMySQL和MySQL开发,推荐以下资源:

  1. 官方文档

    • PyMySQL官方文档
    • MySQL 8.0参考手册
  2. 性能优化

    • 《高性能MySQL》(第4版)
    • MySQL官方优化指南
  3. 安全实践

    • OWASP SQL注入防御手册
    • MySQL安全指南
  4. 进阶工具

    • Percona Toolkit:专业的MySQL管理工具集
    • ProxySQL:高性能MySQL代理
    • Orchestrator:MySQL复制拓扑管理
  5. 监控方案

    • Prometheus + MySQL Exporter
    • Percona Monitoring and Management
    • 阿里云/腾讯云等云厂商的数据库监控服务

在实际项目中持续积累经验,结合性能测试和监控数据不断优化,才能真正掌握PyMySQL的精髓。记住,没有放之四海而皆准的最佳实践,只有适合特定业务场景的合理方案。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/13 7:41:54

ESN回声状态网络:时间序列建模的轻量级动力系统解法

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/13 7:41:51

高通QNN端侧AI部署实战:从模型转换到HTP性能调优

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/13 7:41:23

行星齿轮系统弯扭耦合MATLAB建模与分析

1. 行星齿轮系统的弯扭耦合现象解析行星齿轮系统作为机械传动领域的核心部件&#xff0c;其动力学特性直接影响着整个传动装置的可靠性。在实际运行中&#xff0c;行星齿轮不仅承受着来自扭矩传递的切向力&#xff0c;还会因为制造误差、装配间隙等因素产生径向弯曲振动。这两种…

作者头像 李华
网站建设 2026/9/13 7:41:04

Agent失忆不是模型问题,是记忆架构设计缺陷

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/13 7:38:04

ZeroClaw具身智能执行引擎:Rust驱动的类型安全动作编排

1. ZeroClaw 的“代码执行”到底在执行什么&#xff1f;OpenClaw 是一个具身智能硬件平台&#xff0c;而 ZeroClaw 是其核心开源实现——不是玩具级 Demo&#xff0c;也不是纯软件模拟器&#xff0c;它是一套能真正驱动机械臂、摄像头、麦克风、扬声器乃至 ESP32 微控制器的 Ru…

作者头像 李华