无论你是要存储系统用户信息,还是准备保存复杂的业务数据,掌握如何用 Python 优雅地与 MySQL 交互都是后端的必修课。本文将带你从零开始,使用官方驱动 mysql-connector-python 完成数据库的增删改查(CRUD),并介绍在 Web 框架中极为重要的“连接池”技术。

第一步:环境准备与安装

首先,确保你的环境中已经运行着一个 MySQL 数据库(你可以用之前学过的 Docker 快速启动一个 MySQL 容器)。

然后,在你的 Python 环境中安装官方驱动:

pip install mysql-connector-python

注意:请认准 mysql-connector-python,不要安装已被弃用的 mysql-connector

第二步:建立基础连接与创建表

在与数据库交互时,核心流程永远是:建立连接 -> 获取游标 -> 执行 SQL -> 提交/获取结果 -> 关闭连接

我们先编写一个脚本来连接数据库,并创建一个我们在前几篇博客中用到的 users 表。

import mysql.connector
from mysql.connector import Error

def create_table():
    try:
        # 1. 建立数据库连接
        conn = mysql.connector.connect(
            host='127.0.0.1',
            user='root',
            password='your_password',
            database='your_database' # 请确保该数据库已存在
        )
        
        if conn.is_connected():
            print("成功连接到 MySQL 数据库!")
            
            # 2. 获取游标
            cursor = conn.cursor()
            
            # 3. 编写并执行 SQL 语句
            create_table_query = """
            CREATE TABLE IF NOT EXISTS users (
                id INT AUTO_INCREMENT PRIMARY KEY,
                username VARCHAR(50) NOT NULL,
                role VARCHAR(50) NOT NULL
            )
            """
            cursor.execute(create_table_query)
            print("数据表 `users` 检查/创建成功!")

    except Error as e:
        print(f"连接或执行失败: {e}")
        
    finally:
        # 4. 无论成功与否,务必清理资源
        if 'conn' in locals() and conn.is_connected():
            cursor.close()
            conn.close()
            print("数据库连接已关闭。")

if __name__ == '__main__':
    create_table()

第三步:数据的增、删、改、查(CRUD)

掌握了基础流程后,我们来看看最常用的数据操作。

1. 插入数据 (Insert)

为了提高效率,插入多条数据时推荐使用 executemany

def insert_users(conn):
    cursor = conn.cursor()
    insert_query = "INSERT INTO users (username, role) VALUES (%s, %s)"
    
    # 使用元组列表传递参数,防止 SQL 注入
    users_data = [
        ("admin_alice", "admin"),
        ("dev_bob", "developer"),
        ("guest_charlie", "guest")
    ]
    
    cursor.executemany(insert_query, users_data)
    # 涉及数据修改的操作,必须调用 commit() 才能生效
    conn.commit()
    
    print(f"成功插入了 {cursor.rowcount} 条数据。")

2. 查询数据 (Select) - 字典模式

在使用 FastAPI 这类现代 Web 框架时,我们通常需要将数据转换为 JSON 返回。默认的游标返回的是元组(如 (1, 'admin_alice', 'admin')),阅读和转换起来不够方便。

强烈建议在查询时启用字典游标 (dictionary=True)

def get_all_users(conn):
    # dictionary=True 会将结果映射为字典类型
    cursor = conn.cursor(dictionary=True)
    cursor.execute("SELECT id, username, role FROM users")
    
    records = cursor.fetchall()
    for row in records:
        print(row) 
        # 输出示例: {'id': 1, 'username': 'admin_alice', 'role': 'admin'}
        
    return records

3. 更新 (Update) 与删除 (Delete)

操作逻辑与插入类似,核心在于编写正确的 SQL 并传入参数。

def update_user_role(conn, user_id, new_role):
    cursor = conn.cursor()
    update_query = "UPDATE users SET role = %s WHERE id = %s"
    cursor.execute(update_query, (new_role, user_id))
    conn.commit()

第四步:进阶技巧 —— 使用连接池 (Connection Pool)

如果你打算将这个库整合到之前写的 FastAPI 应用中,千万不要在每次接收到 HTTP 请求时都重新建立一次数据库连接。建立连接是一个极其耗时的网络 I/O 操作。

官方库原生提供了 MySQLConnectionPool,它会在内存中维护一组随时待命的连接。

from mysql.connector import pooling

# 初始化连接池(通常在 FastAPI 启动时执行一次)
dbconfig = {
    "host": "127.0.0.1",
    "user": "root",
    "password": "your_password",
    "database": "your_database"
}

# 创建一个容量为 5 的连接池
connection_pool = pooling.MySQLConnectionPool(
    pool_name="mypool",
    pool_size=5,
    **dbconfig
)

def get_user_from_pool():
    # 从池中获取一个可用连接,用完后直接 close() 即可归还给池子
    conn = connection_pool.get_connection()
    try:
        cursor = conn.cursor(dictionary=True)
        cursor.execute("SELECT * FROM users LIMIT 1")
        return cursor.fetchone()
    finally:
        conn.close() # 这里的 close() 是把连接还给连接池,而不是真正断开物理连接

总结

mysql-connector-python 以其官方背景、纯 Python 实现和简单易懂的 API,非常适合作为操作 MySQL 的起点。掌握了预处理语句(防注入)、dictionary=True(方便数据转换)以及连接池(提升高并发性能)这三大法宝,你已经可以写出非常健壮的数据库交互代码了。