1. Python操作MySQL数据库实战指南
作为Python开发者,数据库操作是必备技能之一。MySQL作为最流行的开源关系型数据库,与Python的结合使用场景非常广泛。本文将深入讲解两种主流的Python MySQL驱动:mysql-connector和PyMySQL,通过完整示例演示从安装配置到CRUD操作的整个流程。
1.1 驱动选择与安装
在Python生态中,主要有两个成熟的MySQL驱动可供选择:
- mysql-connector:MySQL官方提供的纯Python驱动
- PyMySQL:社区维护的纯Python驱动
对于新项目,我通常推荐使用mysql-connector,原因有三:
- 官方维护,兼容性有保障
- 性能优化较好
- 支持MySQL最新特性
安装非常简单,使用pip即可:
bash复制# 安装mysql-connector
python -m pip install mysql-connector-python
# 安装PyMySQL
python -m pip install PyMySQL
注意:如果使用MySQL 8.0+版本,需要特别注意密码认证插件的变化。8.0默认使用caching_sha2_password,而早期版本使用mysql_native_password。为确保兼容性,建议在my.ini中添加:
code复制[mysqld] default_authentication_plugin=mysql_native_password并在MySQL中执行:
sql复制ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '你的密码';
1.2 基础连接与数据库操作
让我们从最基本的数据库连接开始。以下是使用mysql-connector建立连接的示例:
python复制import mysql.connector
# 建立数据库连接
config = {
'host': 'localhost',
'user': 'root',
'password': 'your_password',
'database': 'test_db'
}
try:
conn = mysql.connector.connect(**config)
print("数据库连接成功")
# 创建游标
cursor = conn.cursor()
# 创建数据库
cursor.execute("CREATE DATABASE IF NOT EXISTS my_database")
# 显示所有数据库
cursor.execute("SHOW DATABASES")
for db in cursor:
print(db[0])
except mysql.connector.Error as err:
print(f"数据库错误: {err}")
finally:
if 'conn' in locals() and conn.is_connected():
cursor.close()
conn.close()
关键点说明:
- 连接参数建议使用字典形式,便于管理和复用
- 始终使用try-except处理可能的数据库错误
- 操作完成后确保关闭游标和连接
IF NOT EXISTS可以避免重复创建的错误
2. 表操作与CRUD实战
2.1 创建表与数据类型映射
在操作表之前,我们需要先了解Python与MySQL数据类型的对应关系:
| Python类型 | MySQL类型 | 说明 |
|---|---|---|
| int | INT | 整数 |
| float | FLOAT | 浮点数 |
| str | VARCHAR | 可变长度字符串 |
| bytes | BLOB | 二进制数据 |
| datetime | DATETIME | 日期时间 |
创建表示例:
python复制def create_user_table(conn):
cursor = conn.cursor()
create_table_sql = """
CREATE TABLE IF NOT EXISTS users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL,
email VARCHAR(100) UNIQUE,
age INT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
"""
try:
cursor.execute(create_table_sql)
conn.commit()
print("用户表创建成功")
except mysql.connector.Error as err:
print(f"创建表失败: {err}")
finally:
cursor.close()
2.2 插入数据的最佳实践
插入数据时,有几种不同的方法,各有优缺点:
- 直接拼接SQL语句(不推荐,有SQL注入风险)
- 使用参数化查询(推荐)
- 批量插入(大数据量时高效)
python复制# 单条插入 - 参数化查询
def add_user(conn, username, email, age=None):
cursor = conn.cursor()
sql = "INSERT INTO users (username, email, age) VALUES (%s, %s, %s)"
values = (username, email, age)
try:
cursor.execute(sql, values)
conn.commit()
print(f"用户 {username} 添加成功,ID: {cursor.lastrowid}")
except mysql.connector.Error as err:
print(f"添加用户失败: {err}")
finally:
cursor.close()
# 批量插入
def add_users_bulk(conn, user_list):
cursor = conn.cursor()
sql = "INSERT INTO users (username, email, age) VALUES (%s, %s, %s)"
try:
cursor.executemany(sql, user_list)
conn.commit()
print(f"批量添加了 {cursor.rowcount} 条记录")
except mysql.connector.Error as err:
conn.rollback()
print(f"批量添加失败: {err}")
finally:
cursor.close()
重要提示:始终使用参数化查询(%s占位符)而非字符串拼接,这是防止SQL注入攻击的关键。即使数据来自可信来源,这也是必须遵循的最佳实践。
2.3 查询与结果处理
查询数据后,我们通常需要将结果转换为更适合Python处理的形式。以下是几种常见的结果处理方式:
python复制# 基础查询
def get_all_users(conn):
cursor = conn.cursor(dictionary=True) # 返回字典形式
try:
cursor.execute("SELECT * FROM users")
return cursor.fetchall() # 获取所有记录
finally:
cursor.close()
# 分页查询
def get_users_paginated(conn, page=1, per_page=10):
cursor = conn.cursor(dictionary=True)
offset = (page - 1) * per_page
try:
cursor.execute("SELECT * FROM users LIMIT %s OFFSET %s",
(per_page, offset))
return cursor.fetchall()
finally:
cursor.close()
# 将结果映射为对象
class User:
def __init__(self, id, username, email, age, created_at):
self.id = id
self.username = username
self.email = email
self.age = age
self.created_at = created_at
def get_user_objects(conn):
cursor = conn.cursor()
try:
cursor.execute("SELECT * FROM users")
return [User(*row) for row in cursor.fetchall()]
finally:
cursor.close()
查询优化建议:
- 只查询需要的列,避免
SELECT * - 对大表使用LIMIT分页
- 对常用查询条件添加索引
- 使用
cursor.description可以获取列元信息
2.4 更新与删除操作
更新和删除操作需要特别注意数据一致性和错误处理:
python复制# 更新用户信息
def update_user(conn, user_id, **kwargs):
if not kwargs:
return
cursor = conn.cursor()
set_clause = ", ".join([f"{k} = %s" for k in kwargs])
sql = f"UPDATE users SET {set_clause} WHERE id = %s"
values = list(kwargs.values()) + [user_id]
try:
cursor.execute(sql, values)
conn.commit()
print(f"更新了 {cursor.rowcount} 条记录")
except mysql.connector.Error as err:
conn.rollback()
print(f"更新失败: {err}")
finally:
cursor.close()
# 删除用户
def delete_user(conn, user_id):
cursor = conn.cursor()
try:
cursor.execute("DELETE FROM users WHERE id = %s", (user_id,))
conn.commit()
print(f"删除了 {cursor.rowcount} 条记录")
except mysql.connector.Error as err:
conn.rollback()
print(f"删除失败: {err}")
finally:
cursor.close()
关键注意事项:
- 更新操作前最好先检查数据是否存在
- 重要数据考虑逻辑删除而非物理删除
- 始终在事务中执行相关操作,确保一致性
- 批量操作时注意性能影响
3. PyMySQL与mysql-connector对比
3.1 基本用法差异
PyMySQL是另一个流行的MySQL驱动,API与mysql-connector类似但有一些差异:
python复制import pymysql
# 连接方式略有不同
conn = pymysql.connect(
host='localhost',
user='root',
password='your_password',
database='test_db',
charset='utf8mb4',
cursorclass=pymysql.cursors.DictCursor
)
# 查询示例
try:
with conn.cursor() as cursor:
sql = "SELECT * FROM users WHERE age > %s"
cursor.execute(sql, (18,))
result = cursor.fetchall()
for row in result:
print(row)
finally:
conn.close()
主要区别:
- 连接参数名称略有不同(如charset而非character_set)
- PyMySQL默认自动提交为False,而mysql-connector为True
- 错误处理机制稍有不同
3.2 性能与特性比较
| 特性 | mysql-connector | PyMySQL |
|---|---|---|
| 维护者 | Oracle官方 | 社区 |
| Python兼容 | 2.7+和3.x | 3.x |
| 协议 | 纯Python + C扩展 | 纯Python |
| 连接池 | 支持 | 需要第三方 |
| 异步支持 | 有 | 需要aiomysql |
| 性能 | 较高 | 中等 |
| 文档 | 完善 | 良好 |
选择建议:
- 需要官方支持/最新特性 → mysql-connector
- 需要纯Python实现 → PyMySQL
- 需要连接池 → mysql-connector
- 需要异步支持 → aiomysql(PyMySQL分支)
4. 高级主题与最佳实践
4.1 连接池管理
频繁创建和关闭连接会影响性能。使用连接池是生产环境的必备方案:
python复制from mysql.connector import pooling
# 创建连接池
dbconfig = {
"host": "localhost",
"user": "root",
"password": "your_password",
"database": "test_db"
}
connection_pool = pooling.MySQLConnectionPool(
pool_name="mypool",
pool_size=5,
pool_reset_session=True,
**dbconfig
)
# 从连接池获取连接
def get_users():
try:
conn = connection_pool.get_connection()
cursor = conn.cursor(dictionary=True)
cursor.execute("SELECT * FROM users LIMIT 10")
return cursor.fetchall()
except mysql.connector.Error as err:
print(f"Error: {err}")
finally:
if 'conn' in locals() and conn.is_connected():
cursor.close()
conn.close() # 实际是返回到连接池
连接池配置建议:
- 根据应用负载调整pool_size
- 生产环境建议10-20个连接
- 使用with语句自动管理连接生命周期
- 监控连接使用情况,避免泄漏
4.2 事务处理模式
正确处理事务对数据一致性至关重要:
python复制def transfer_funds(conn, from_id, to_id, amount):
cursor = conn.cursor()
try:
# 开始事务
conn.start_transaction()
# 扣款
cursor.execute("UPDATE accounts SET balance = balance - %s WHERE id = %s",
(amount, from_id))
if cursor.rowcount != 1:
raise ValueError("扣款账户不存在")
# 存款
cursor.execute("UPDATE accounts SET balance = balance + %s WHERE id = %s",
(amount, to_id))
if cursor.rowcount != 1:
raise ValueError("收款账户不存在")
# 提交事务
conn.commit()
print("转账成功")
except Exception as err:
conn.rollback()
print(f"转账失败,已回滚: {err}")
finally:
cursor.close()
事务最佳实践:
- 保持事务尽可能短小
- 明确处理所有可能的错误
- 考虑使用保存点(SAVEPOINT)处理复杂事务
- 避免在事务中执行耗时操作
4.3 ORM集成示例
虽然直接使用驱动很灵活,但ORM可以大幅提高开发效率。以下是SQLAlchemy集成示例:
python复制from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
# 连接字符串格式: mysql+mysqlconnector://user:password@host/database
DATABASE_URI = "mysql+mysqlconnector://root:your_password@localhost/test_db"
engine = create_engine(DATABASE_URI)
Base = declarative_base()
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
username = Column(String(50), nullable=False)
email = Column(String(100), unique=True)
age = Column(Integer)
# 创建表
Base.metadata.create_all(engine)
# 创建会话
Session = sessionmaker(bind=engine)
session = Session()
# 使用示例
new_user = User(username='alice', email='alice@example.com', age=25)
session.add(new_user)
session.commit()
# 查询
users = session.query(User).filter(User.age >= 18).all()
for user in users:
print(user.username, user.email)
ORM选择建议:
- 需要完整功能 → SQLAlchemy
- 需要简单易用 → peewee
- 需要异步支持 → TortoiseORM
- 需要Django集成 → Django ORM
5. 常见问题与性能优化
5.1 连接问题排查
问题1:无法连接到数据库
可能原因:
- 用户名/密码错误
- 主机地址不正确
- 防火墙阻止了3306端口
- MySQL服务未运行
解决方案:
bash复制# 检查MySQL服务状态
sudo systemctl status mysql
# 测试网络连接
telnet localhost 3306
# 检查用户权限
mysql -u root -p -e "SELECT host, user FROM mysql.user;"
问题2:连接超时
配置建议:
python复制conn = mysql.connector.connect(
host='localhost',
user='root',
password='your_password',
database='test_db',
connect_timeout=30, # 连接超时(秒)
connection_attributes={
'program_name': 'my_app' # 标识连接来源
}
)
5.2 查询性能优化
- 索引优化
sql复制-- 添加合适索引
ALTER TABLE users ADD INDEX idx_email (email);
ALTER TABLE users ADD INDEX idx_age (age);
-- 查看查询执行计划
EXPLAIN SELECT * FROM users WHERE age > 18;
- 批量操作
python复制# 批量插入比单条插入快10-100倍
data = [(f'user{i}', f'user{i}@example.com', i) for i in range(1000)]
cursor.executemany("INSERT INTO users (username, email, age) VALUES (%s, %s, %s)", data)
- 服务器端游标
python复制# 对于大结果集,使用服务器端游标
cursor = conn.cursor(buffered=False) # mysql-connector
cursor = conn.cursor(pymysql.cursors.SSCursor) # PyMySQL
5.3 安全最佳实践
- 永远不要拼接SQL
python复制# 错误做法(有SQL注入风险)
cursor.execute(f"SELECT * FROM users WHERE username = '{username}'")
# 正确做法(参数化查询)
cursor.execute("SELECT * FROM users WHERE username = %s", (username,))
- 最小权限原则
sql复制-- 创建专用数据库用户
CREATE USER 'app_user'@'%' IDENTIFIED BY 'strong_password';
GRANT SELECT, INSERT, UPDATE ON test_db.* TO 'app_user'@'%';
- 连接安全配置
python复制conn = mysql.connector.connect(
ssl_disabled=False, # 启用SSL
ssl_ca='/path/to/ca.pem',
ssl_cert='/path/to/client-cert.pem',
ssl_key='/path/to/client-key.pem'
)
6. 实际项目中的应用模式
6.1 使用上下文管理器管理连接
Python的上下文管理器非常适合管理数据库连接资源:
python复制from contextlib import contextmanager
@contextmanager
def get_db_connection():
conn = None
try:
conn = mysql.connector.connect(
host='localhost',
user='root',
password='your_password',
database='test_db'
)
yield conn
except mysql.connector.Error as err:
print(f"数据库错误: {err}")
raise
finally:
if conn and conn.is_connected():
conn.close()
# 使用示例
with get_db_connection() as conn:
cursor = conn.cursor()
cursor.execute("SELECT * FROM users")
for row in cursor:
print(row)
cursor.close()
6.2 数据库操作封装类
对于大型项目,建议封装一个数据库操作类:
python复制class Database:
def __init__(self, config):
self.config = config
self.pool = self._create_pool()
def _create_pool(self):
return pooling.MySQLConnectionPool(
pool_name="mypool",
pool_size=5,
**self.config
)
@contextmanager
def get_cursor(self, dictionary=False):
conn = self.pool.get_connection()
try:
cursor = conn.cursor(dictionary=dictionary)
yield cursor
conn.commit()
except Exception as e:
conn.rollback()
raise e
finally:
cursor.close()
conn.close()
def execute(self, sql, params=None):
with self.get_cursor() as cursor:
cursor.execute(sql, params or ())
return cursor.rowcount
def fetch_all(self, sql, params=None, dictionary=False):
with self.get_cursor(dictionary=dictionary) as cursor:
cursor.execute(sql, params or ())
return cursor.fetchall()
# 使用示例
db_config = {
"host": "localhost",
"user": "root",
"password": "your_password",
"database": "test_db"
}
db = Database(db_config)
users = db.fetch_all("SELECT * FROM users WHERE age > %s", (18,), dictionary=True)
6.3 异步IO支持
对于现代Python异步应用,可以使用aiomysql:
python复制import asyncio
import aiomysql
async def fetch_users():
pool = await aiomysql.create_pool(
host='localhost',
user='root',
password='your_password',
db='test_db',
minsize=5,
maxsize=10
)
async with pool.acquire() as conn:
async with conn.cursor(aiomysql.DictCursor) as cursor:
await cursor.execute("SELECT * FROM users")
result = await cursor.fetchall()
print(result)
pool.close()
await pool.wait_closed()
# 运行
loop = asyncio.get_event_loop()
loop.run_until_complete(fetch_users())
7. 测试与调试技巧
7.1 单元测试数据库代码
使用unittest测试数据库代码的示例:
python复制import unittest
from unittest.mock import Mock, patch
class TestDatabaseOperations(unittest.TestCase):
@patch('mysql.connector.connect')
def test_add_user(self, mock_connect):
# 设置mock
mock_conn = Mock()
mock_cursor = Mock()
mock_connect.return_value = mock_conn
mock_conn.cursor.return_value = mock_cursor
# 调用被测函数
add_user(mock_conn, "testuser", "test@example.com", 30)
# 验证
mock_cursor.execute.assert_called_once_with(
"INSERT INTO users (username, email, age) VALUES (%s, %s, %s)",
("testuser", "test@example.com", 30)
)
mock_conn.commit.assert_called_once()
if __name__ == '__main__':
unittest.main()
7.2 使用测试数据库
为测试专门配置一个测试数据库:
python复制import pytest
@pytest.fixture
def test_db():
# 创建测试数据库连接
conn = mysql.connector.connect(
host='localhost',
user='test_user',
password='test_password',
database='test_db_test'
)
# 创建测试表
cursor = conn.cursor()
cursor.execute("""
CREATE TABLE IF NOT EXISTS users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL,
email VARCHAR(100) UNIQUE
)
""")
conn.commit()
yield conn
# 测试后清理
cursor.execute("DROP TABLE IF EXISTS users")
conn.commit()
conn.close()
def test_user_operations(test_db):
# 测试添加用户
add_user(test_db, "testuser", "test@example.com")
# 验证用户已添加
cursor = test_db.cursor(dictionary=True)
cursor.execute("SELECT * FROM users WHERE username = %s", ("testuser",))
user = cursor.fetchone()
assert user is not None
assert user['email'] == "test@example.com"
7.3 性能分析与优化
使用Python内置工具分析数据库操作性能:
python复制import cProfile
import pstats
def profile_database_operations():
conn = mysql.connector.connect(
host='localhost',
user='root',
password='your_password',
database='test_db'
)
# 性能测试函数
def test_query():
cursor = conn.cursor()
for i in range(1000):
cursor.execute("SELECT * FROM users WHERE id = %s", (i % 100 + 1,))
cursor.fetchone()
cursor.close()
# 运行性能分析
profiler = cProfile.Profile()
profiler.enable()
test_query()
profiler.disable()
# 输出结果
stats = pstats.Stats(profiler)
stats.sort_stats('cumtime')
stats.print_stats(10)
conn.close()
profile_database_operations()
8. 生产环境部署建议
8.1 连接参数优化
生产环境推荐配置:
python复制production_config = {
'host': 'mysql-cluster.prod.example.com',
'user': 'app_prod',
'password': 'complex_password_123',
'database': 'app_db',
'port': 3306,
'autocommit': False, # 显式控制事务
'pool_name': 'prod_pool',
'pool_size': 15,
'pool_reset_session': True,
'connect_timeout': 10,
'connection_attributes': {
'program_name': 'production_app_v1.2'
},
'failover': [ # 故障转移配置
{
'host': 'mysql-replica1.prod.example.com',
'port': 3306
},
{
'host': 'mysql-replica2.prod.example.com',
'port': 3306
}
]
}
8.2 监控与日志
添加数据库操作日志:
python复制import logging
# 配置日志
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger('db')
class LoggingCursor:
def __init__(self, cursor):
self.cursor = cursor
def execute(self, sql, params=None):
logger.info(f"Executing SQL: {sql} with params: {params}")
start = time.time()
try:
return self.cursor.execute(sql, params or ())
finally:
duration = time.time() - start
logger.info(f"Query took {duration:.3f} seconds")
def __getattr__(self, name):
return getattr(self.cursor, name)
# 使用日志游标
conn = mysql.connector.connect(...)
cursor = LoggingCursor(conn.cursor())
cursor.execute("SELECT * FROM users WHERE age > %s", (18,))
8.3 备份与恢复策略
自动化数据库备份方案:
python复制import subprocess
from datetime import datetime
def backup_database():
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
backup_file = f"/backups/mysql_backup_{timestamp}.sql"
try:
subprocess.run([
'mysqldump',
'--host=localhost',
'--user=root',
'--password=your_password',
'test_db',
'--result-file=' + backup_file,
'--single-transaction',
'--routines',
'--triggers'
], check=True)
print(f"备份成功: {backup_file}")
except subprocess.CalledProcessError as e:
print(f"备份失败: {e}")
# 定期备份
backup_database()
恢复备份:
bash复制mysql -u root -p test_db < /backups/mysql_backup_20230801_143000.sql
9. 扩展与进阶方向
9.1 分库分表策略
随着数据量增长,可能需要考虑分库分表。常见策略:
-
水平分表:按行拆分到多个结构相同的表
- 例如:user_0, user_1,...user_n
- 路由方式:user_id % n
-
垂直分表:按列拆分到不同表
- 例如:user_basic, user_profile, user_stats
-
分库:将表分布到不同数据库实例
实现示例:
python复制class ShardedDatabase:
def __init__(self, shards):
self.shards = shards # 分片配置列表
def get_connection(self, shard_key):
# 根据分片键选择连接
shard_index = shard_key % len(self.shards)
return mysql.connector.connect(**self.shards[shard_index])
def get_user(self, user_id):
conn = self.get_connection(user_id)
try:
cursor = conn.cursor(dictionary=True)
table = f"users_{user_id % 10}" # 10个分表
cursor.execute(f"SELECT * FROM {table} WHERE id = %s", (user_id,))
return cursor.fetchone()
finally:
cursor.close()
conn.close()
9.2 读写分离实现
对于读多写少的应用,读写分离可以显著提高性能:
python复制class ReadWriteSplitting:
def __init__(self, master_config, replica_configs):
self.master = master_config
self.replicas = replica_configs
self.replica_index = 0
def get_master(self):
return mysql.connector.connect(**self.master)
def get_replica(self):
# 简单轮询选择副本
config = self.replicas[self.replica_index]
self.replica_index = (self.replica_index + 1) % len(self.replicas)
return mysql.connector.connect(**config)
def execute_write(self, sql, params=None):
conn = self.get_master()
try:
cursor = conn.cursor()
cursor.execute(sql, params or ())
conn.commit()
return cursor.rowcount
finally:
cursor.close()
conn.close()
def execute_read(self, sql, params=None):
conn = self.get_replica()
try:
cursor = conn.cursor(dictionary=True)
cursor.execute(sql, params or ())
return cursor.fetchall()
finally:
cursor.close()
conn.close()
9.3 数据迁移与ETL
使用Python进行数据库间数据迁移:
python复制def migrate_data(source_config, target_config, table):
source_conn = mysql.connector.connect(**source_config)
target_conn = mysql.connector.connect(**target_config)
try:
source_cursor = source_conn.cursor(dictionary=True)
target_cursor = target_conn.cursor()
# 获取源数据
source_cursor.execute(f"SELECT * FROM {table}")
# 准备插入语句
cols = [col[0] for col in source_cursor.description]
placeholders = ", ".join(["%s"] * len(cols))
insert_sql = f"INSERT INTO {table} ({', '.join(cols)}) VALUES ({placeholders})"
# 批量迁移
batch_size = 1000
while True:
rows = source_cursor.fetchmany(batch_size)
if not rows:
break
# 转换字典行为值元组
values = [tuple(row.values()) for row in rows]
target_cursor.executemany(insert_sql, values)
target_conn.commit()
print(f"迁移了 {len(rows)} 条记录")
finally:
source_cursor.close()
target_cursor.close()
source_conn.close()
target_conn.close()
10. 现代替代方案与趋势
10.1 MySQL替代方案比较
除了传统MySQL驱动,现代Python生态还有其他选择:
- asyncpg:专注于PostgreSQL的异步驱动
- psycopg3:PostgreSQL的现代同步/异步驱动
- SQLite3:内嵌数据库,适合小型应用
- MongoDB驱动:面向文档的NoSQL方案
10.2 云数据库集成
主流云数据库服务集成示例:
AWS RDS连接示例:
python复制import boto3
import mysql.connector
# 获取RDS认证令牌
client = boto3.client('rds')
token = client.generate_db_auth_token(
DBHostname='my-cluster.cluster-123456789012.us-east-1.rds.amazonaws.com',
Port=3306,
DBUsername='app_user',
Region='us-east-1'
)
# 连接RDS MySQL
conn = mysql.connector.connect(
host='my-cluster.cluster-123456789012.us-east-1.rds.amazonaws.com',
user='app_user',
password=token,
database='app_db',
ssl_ca='/path/to/rds-combined-ca-bundle.pem'
)
Azure Database for MySQL连接示例:
python复制conn = mysql.connector.connect(
host='my-server.mysql.database.azure.com',
user='my_user@my-server',
password='my_password',
database='my_database',
ssl_ca='/path/to/BaltimoreCyberTrustRoot.crt.pem',
ssl_verify_cert=True
)
10.3 未来趋势观察
- 异步成为标配:随着async/await普及,异步驱动将成为主流
- ORM与原生SQL融合:既需要ORM的便利,也需要原生SQL的性能
- 云原生集成:与云服务的深度集成,如自动凭证轮换
- 数据分析支持:更好的大数据量处理能力
在实际项目中,我通常会根据团队技术栈和项目需求选择合适的方案。对于大多数Python+MySQL项目,mysql-connector提供了良好的平衡点,而PyMySQL则更适合需要纯Python实现的场景。无论选择哪种驱动,遵循本文介绍的最佳实践都能帮助您构建健壮、高效的数据库应用。