悠闲博客-blog.yxrjt.cn

Python操作MySQL数据库

更新时间:2025-09-24 10:02点击:51

一、MySQL 数据库与 Python 交互基础概述

在现代 Web 应用开发体系中,数据库作为数据存储与管理的核心组件,其重要性不言而喻。MySQL 凭借开源、轻量、高可靠性等特性,成为关系型数据库领域的主流选择之一。Python 作为全栈开发的热门语言,通过丰富的生态库实现了与 MySQL 的无缝交互,使得开发者能够高效地完成数据的增删改查、事务管理及性能优化等操作。

1.1 核心技术栈与开发环境准备

1.1.1 主流连接库对比与选择

Python 操作 MySQL 的核心连接库主要包括官方推荐的mysql-connector-python和社区主流的PyMySQL。两者功能对比如下:


特性 mysql-connector-python PyMySQL

兼容性 原生支持 Python 3.x 纯 Python 实现,兼容性广泛

性能 中等偏上(C 扩展实现) 中等(纯 Python 实现)

生态集成 与 MySQL 官方工具链集成更好 适配 Django 等框架更便捷

学习成本 需要了解官方 API 细节 语法简洁,接近 Python 风格

实践建议:在中小型项目中优先选择PyMySQL,其语法简洁且适配主流 Web 框架(如 Django);若涉及 MySQL 原生协议深度定制,可考虑mysql-connector-python。


1.1.2 环境搭建与库安装

# 安装PyMySQL(推荐方案)

pip install pymysql

 

# 安装mysql-connector-python(备选方案)

pip install mysql-connector-python

AI写代码

二、Python 与 MySQL 数据库的基础连接与操作

2.1 数据库连接的建立与释放

2.1.1 连接参数详解

使用pymysql.connect()方法建立连接时,核心参数说明如下:


host:数据库服务器地址(本地默认localhost或127.0.0.1)

user:数据库用户名(默认root)

password:用户密码(需根据实际配置填写)

database:目标数据库名称(需提前创建)

port:端口号(默认3306,可省略)

charset:字符集(推荐设置utf8mb4以支持 Emoji 等特殊字符)

代码示例:


运行


import pymysql

 

# 建立数据库连接

db = pymysql.connect(

    host="localhost",

    user="root",

    password="your_password",

    database="testdb",

    charset="utf8mb4"

)

AI写代码


2.1.2 游标对象的创建与作用

游标(Cursor)是执行 SQL 语句的核心接口,通过db.cursor()方法创建。其主要作用包括:


执行 SQL 语句(含单条与批量操作)

处理查询结果(获取单条或多条记录)

支持事务上下文管理

注意事项:游标对象需在使用完毕后通过cursor.close()显式关闭,避免资源泄漏。


2.2 核心 SQL 操作的 Python 实现

2.2.1 数据查询(SELECT)

基础查询

运行


# 创建游标

cursor = db.cursor()

 

# 执行查询语句

cursor.execute("SELECT * FROM users WHERE age > %s", (18,))

 

# 获取所有结果

results = cursor.fetchall()

for row in results:

    print(f"用户信息:{row}")

 

# 获取单条结果

single_result = cursor.fetchone()

print(f"单条记录:{single_result}")

AI写代码


模糊查询与联合查询

模糊查询(LIKE):

运行


cursor.execute("SELECT * FROM users WHERE name LIKE %s", ("%zh%",))

AI写代码

联合查询(JOIN):

运行


cursor.execute("""

    SELECT u.name, o.amount 

    FROM users u

    INNER JOIN orders o ON u.id = o.user_id

    WHERE u.age > 25

""")

AI写代码

2.2.2 数据插入(INSERT)

单条插入

运行


# 安全参数化查询(防止SQL注入)

sql = "INSERT INTO users (name, age, email) VALUES (%s, %s, %s)"

values = ("Alice", 25, "alice@example.com")

cursor.execute(sql, values)

db.commit()  # 提交事务

AI写代码

批量插入

运行


# 使用executemany批量插入

batch_data = [

    ("Bob", 30, "bob@example.com"),

    ("Charlie", 35, "charlie@example.com")

]

cursor.executemany(sql, batch_data)

db.commit()

AI写代码

2.2.3 数据更新(UPDATE)

运行


# 更新单条记录

update_sql = "UPDATE users SET age = %s WHERE name = %s"

cursor.execute(update_sql, (26, "Alice"))

db.commit()

 

# 批量更新(根据条件)

cursor.execute("UPDATE users SET email = CONCAT(name, '@company.com') WHERE age > 30")

db.commit()

AI写代码

2.2.4 数据删除(DELETE)

运行


# 删除单条记录

delete_sql = "DELETE FROM users WHERE name = %s"

cursor.execute(delete_sql, ("Alice",))

db.commit()

 

# 批量删除(清空表)

cursor.execute("DELETE FROM users")  # 慎用!需确保条件安全

db.commit()

AI写代码

三、事务管理:保证数据一致性的核心机制

3.1 事务的基本概念与特性(ACID)

事务是由一组 SQL 操作组成的逻辑单元,具有以下特性:


原子性(Atomicity):所有操作要么全部成功,要么全部回滚

一致性(Consistency):事务执行前后数据状态保持合法

隔离性(Isolation):并发事务间相互隔离,互不干扰

持久性(Durability):已提交事务的变更永久保存

3.2 事务的生命周期管理

3.2.1 显式事务操作流程

运行


try:

    # 开启事务(隐式开启,执行SQL即启动)

    # 执行第一条SQL语句时自动开始事务

    cursor.execute("START TRANSACTION")  # 显式开启(可选)

 

    # 业务操作1:插入用户

    cursor.execute("INSERT INTO users (name) VALUES (%s)", ("Eve",))

    

    # 业务操作2:插入订单(依赖用户ID)

    cursor.execute("""

        INSERT INTO orders (user_id, amount) 

        VALUES ((SELECT LAST_INSERT_ID()), 199.99)

    """)

    

    # 所有操作成功,提交事务

    db.commit()

    print("事务提交成功")

 

except pymysql.MySQLError as e:

    # 发生异常,回滚事务

    db.rollback()

    print(f"事务回滚:{str(e)}")

 

finally:

    # 释放资源

    cursor.close()

    db.close()

AI写代码


3.2.2 自动提交模式(autocommit)

默认行为:pymysql默认开启自动提交(autocommit=True),每条 SQL 语句执行后立即提交

手动模式:设置conn.autocommit = False后,需显式调用commit()或rollback()

最佳实践:在业务逻辑中使用显式事务,避免自动提交导致的一致性风险。


3.3 事务隔离级别:平衡一致性与性能

MySQL 支持四种隔离级别,从低到高依次为:


3.3.1 未提交读(READ UNCOMMITTED)

特性:允许读取未提交数据,可能出现脏读

性能:最高(锁竞争最小)

适用场景:非关键业务(如日志统计)

设置方法:

python


cursor.execute("SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED")

AI写代码

3.3.2 提交读(READ COMMITTED)

特性:只能读取已提交数据,避免脏读,但可能出现不可重复读

性能:中等(MySQL 默认隔离级别为可重复读,需手动设置)

适用场景:大多数业务场景(如电商订单查询)

设置方法:

运行


cursor.execute("SET TRANSACTION ISOLATION LEVEL READ COMMITTED")

AI写代码

3.3.3 可重复读(REPEATABLE READ)

特性:保证事务内多次读取结果一致,避免不可重复读,但可能出现幻读

性能:中等偏下(依赖 MVCC 机制)

适用场景:金融交易、库存管理

设置方法:

运行


cursor.execute("SET TRANSACTION ISOLATION LEVEL REPEATABLE READ")

AI写代码

3.3.4 串行化(SERIALIZABLE)

特性:最高隔离级别,完全串行执行事务,避免所有并发问题

性能:最低(锁粒度大,易出现锁竞争)

适用场景:高一致性需求场景(如银行转账)

设置方法:

运行


cursor.execute("SET TRANSACTION ISOLATION LEVEL SERIALIZABLE")

AI写代码

3.3.5 隔离级别对比表

隔离级别 脏读 不可重复读 幻读 性能影响 默认支持

READ UNCOMMITTED 允许 允许 允许

READ COMMITTED 禁止 允许 允许

REPEATABLE READ 禁止 禁止 允许 中高 是(MySQL)

SERIALIZABLE 禁止 禁止 禁止

选择策略:


优先使用默认的REPEATABLE READ,通过 MVCC 机制在一致性与性能间取得平衡


高并发读场景可降级为READ COMMITTED(需修改 MySQL 全局配置)


写冲突频繁场景谨慎使用SERIALIZABLE,避免性能瓶颈


四、连接池技术:高并发场景的性能优化核心

4.1 连接池的核心优势

传统的数据库连接方式在高并发场景下存在以下问题:


频繁创建 / 销毁连接带来高开销(TCP 三次握手 / 四次挥手)


连接数无限制可能导致数据库服务器资源耗尽


连接池通过预创建一定数量的连接并重复利用,解决了上述问题,其核心优势包括:


性能提升:减少连接创建时间(毫秒级优化)

资源控制:通过maxconnections限制最大连接数

连接复用:避免重复认证与协议协商开销

4.2 使用 DBUtils 实现连接池

4.2.1 安装 DBUtils 库

pip install dbutils

AI写代码

4.2.2 连接池创建与配置

运行


from dbutils.pooled_db import PooledDB

import pymysql

 

# 连接池配置参数

config = {

    "host": "localhost",

    "user": "root",

    "password": "your_password",

    "database": "testdb",

    "charset": "utf8mb4",

    "cursorclass": pymysql.cursors.DictCursor  # 返回字典类型结果

}

 

# 创建连接池(核心参数详解)

pool = PooledDB(

    creator=pymysql,          # 使用PyMySQL作为连接创建工具

    maxconnections=10,        # 最大连接数(同时允许的最大活跃连接)

    mincached=5,              # 初始化时创建的空闲连接数

    maxcached=8,              # 最大空闲连接数(超过则释放)

    maxshared=3,              # 最大共享连接数(0表示不共享)

    blocking=True,            # 连接池无连接时是否阻塞等待

    maxusage=1000,            # 单个连接最大使用次数(避免内存泄漏)

    **config

)

AI写代码


4.2.3 连接池的使用流程

运行


# 从连接池获取连接

with pool.connection() as conn:

    with conn.cursor() as cursor:

        # 执行查询操作

        cursor.execute("SELECT * FROM users LIMIT 5")

        results = cursor.fetchall()

        print("查询结果:", results)

    

    # 退出with块时自动提交事务(未手动开启事务时)

    # 若手动开启事务,需显式调用conn.commit()

 

# 连接自动归还至连接池,无需手动关闭

AI写代码


4.2.4 性能优化参数调优

maxconnections:建议设置为数据库服务器max_connections的 10%-20%(默认 100)

mincached与maxcached:根据并发峰值调整,高并发场景可设置mincached=maxconnections

maxusage:防止连接长时间使用导致的隐性问题,建议设置为 1000-5000 次

4.3 连接池与上下文管理器(with 语句)

利用 Python 的上下文管理器特性,可简化连接池的使用代码,确保连接及时释放:


运行


# 推荐写法:自动管理连接生命周期

with pool.connection() as conn:

    with conn.cursor() as cursor:

        cursor.execute("INSERT INTO users (name) VALUES (%s)", ("Frank",))

    conn.commit()  # 手动提交事务(如需)

AI写代码

五、错误处理与最佳实践

5.1 常见异常类型与捕获

5.1.1 连接异常

pymysql.ConnectError:数据库连接失败(地址错误、权限不足等)

pymysql.OperationalError:连接中断(服务器重启、超时等)

5.1.2 SQL 执行异常

pymysql.DataError:数据类型不匹配(如插入超出字段长度的值)

pymysql.IntegrityError:唯一约束 / 外键约束冲突

pymysql.ProgrammingError:SQL 语法错误

5.1.3 事务异常

pymysql.InternalError:事务操作失败(如锁等待超时)

异常处理模板:


运行


try:

    with pool.connection() as conn:

        with conn.cursor() as cursor:

            cursor.execute("危险操作SQL")

        conn.commit()

except pymysql.MySQLError as e:

    # 记录详细日志(包含SQL语句与参数)

    logger.error(f"数据库操作失败:{str(e)},SQL:{cursor._last_executed}")

    conn.rollback()

    raise  # 向上层抛出异常或自行处理

AI写代码


5.2 安全编码规范

5.2.1 防止 SQL 注入

强制使用参数化查询:永远不要拼接 SQL 字符串,使用%s占位符

避免动态生成 SQL:复杂查询可使用 ORM 框架(如 SQLAlchemy)

权限最小化原则:为应用创建独立数据库用户,限制操作权限

5.2.2 敏感数据处理

密码等敏感字段需加密存储(推荐使用 bcrypt 等哈希算法)

避免在日志中输出完整 SQL 语句(尤其是包含敏感参数的语句)

5.3 性能优化清单

索引优化:为高频查询字段添加索引(避免 SELECT *,使用覆盖索引)

批量操作:使用executemany替代循环单条插入

连接池调优:根据并发量调整maxconnections与缓存参数

事务精简:缩短事务作用域,避免长事务占用锁资源

慢查询分析:开启 MySQL 慢查询日志,优化执行时间超过阈值的 SQL

六、实战案例:电商订单系统的数据操作

6.1 场景描述

实现一个电商订单创建功能,包含以下步骤:


检查用户余额是否充足

扣除用户余额

创建订单记录

记录交易日志

整个过程需保证事务一致性

6.2 代码实现(使用连接池与事务)

运行


from dbutils.pooled_db import PooledDB

import pymysql

 

# 初始化连接池(全局单例)

pool = PooledDB(

    creator=pymysql,

    maxconnections=20,

    **{

        "host": "localhost",

        "user": "app_user",

        "password": "secure_password",

        "database": "ecommerce",

        "charset": "utf8mb4",

        "cursorclass": pymysql.cursors.DictCursor

    }

)

 

def create_order(user_id, product_id, amount

AI写代码


6.2 代码实现(使用连接池与事务)(续)

运行


    try:

        # 从连接池获取连接

        with pool.connection() as conn:

            # 关闭自动提交,开启显式事务

            conn.autocommit = False

            with conn.cursor() as cursor:

                # 1. 检查用户余额是否充足

                cursor.execute(

                    "SELECT balance FROM users WHERE id = %s",

                    (user_id,)

                )

                user_balance = cursor.fetchone().get("balance", 0)

                

                if user_balance < amount:

                    raise ValueError("Insufficient balance")

                

                # 2. 扣除用户余额

                cursor.execute(

                    "UPDATE users SET balance = balance - %s WHERE id = %s",

                    (amount, user_id)

                )

                

                # 3. 创建订单记录

                cursor.execute(

                    """

                    INSERT INTO orders (user_id, product_id, amount, status)

                    VALUES (%s, %s, %s, 'created')

                    """,

                    (user_id, product_id, amount)

                )

                order_id = cursor.lastrowid  # 获取最新插入的订单ID

                

                # 4. 记录交易日志

                cursor.execute(

                    """

                    INSERT INTO transaction_logs (user_id, order_id, type, amount)

                    VALUES (%s, %s, 'debit', %s)

                    """,

                    (user_id, order_id, amount)

                )

                

                # 所有操作成功,提交事务

                conn.commit()

                return {"order_id": order_id, "status": "success"}

    

    except pymysql.MySQLError as e:

        # 事务回滚

        conn.rollback()

        # 记录详细错误日志(包含SQL语句)

        logger.error(f"Database error: {str(e)}, last SQL: {cursor._last_executed}")

        raise RuntimeError("Order creation failed due to database error") from e

    

    except ValueError as e:

        # 业务逻辑异常

        raise RuntimeError(str(e)) from e

    

    finally:

        # 连接自动归还至连接池,无需手动关闭

        pass

AI写代码


6.3 案例优化点分析

事务作用域控制:通过conn.autocommit = False显式管理事务,确保 4 个操作要么全部成功,要么全部回滚。

锁粒度优化:使用行级锁(默认 InnoDB 引擎)避免表级锁,提升并发性能。

异常分层处理:区分数据库底层异常(MySQLError)与业务逻辑异常(ValueError),便于上层服务处理。

七、高级主题:异步操作与 ORM 框架集成

7.1 异步数据库操作(asyncio + aiomysql)

在 Python 3.7 + 异步编程场景中,可使用aiomysql库实现非阻塞数据库操作:


运行


import asyncio

import aiomysql

 

async def async_query():

    # 创建异步连接池

    async with aiomysql.create_pool(

        host='localhost',

        user='root',

        password='password',

        db='testdb',

        loop=asyncio.get_running_loop()

    ) as pool:

        async with pool.acquire() as conn:

            async with conn.cursor() as cursor:

                await cursor.execute("SELECT * FROM users LIMIT 5")

                results = await cursor.fetchall()

                print("Async results:", results)

 

asyncio.run(async_query())

AI写代码


7.2 ORM 框架对比与选择

框架 特点 适用场景

SQLAlchemy 全功能 ORM,支持复杂查询构建,学习曲线较陡 大型项目、复杂业务逻辑

Django ORM 与 Django 框架深度集成,语法简洁,自动生成管理后台 Django 项目

Peewee 轻量级 ORM,文档友好,适合快速原型开发 中小型项目、Flask 框架

Tortoise-ORM 异步 ORM,支持 FastAPI 等异步框架,语法接近 SQLAlchemy 异步 Web 服

八、性能监控与优化工具链

8.1 数据库层面监控

慢查询日志:

-- 开启慢查询日志(全局临时生效)

SET GLOBAL slow_query_log = ON;

SET GLOBAL long_query_time = 1; -- 设置慢查询阈值为1秒

AI写代码

实时状态查询:

SHOW PROCESSLIST; -- 查看当前连接状态

SHOW ENGINE INNODB STATUS; -- 查看InnoDB引擎状态(锁信息、事务情况)

AI写代码

8.2 Python 代码性能分析

cProfile:定位代码中的性能瓶颈


运行


import cProfile

 

def profile_db_operation():

    # 执行数据库操作代码...

 

cProfile.run("profile_db_operation()")

AI写代码

连接池监控:通过DBUtils提供的统计接口获取连接池状态

运行


print(f"Current connections in pool: {pool.connections}")

print(f"Idle connections: {pool.idle_count}")

AI写代码

九、常见问题与解决方案

9.1 连接超时问题

现象:pymysql.OperationalError: 2006 (HY000): MySQL server has gone away

原因:数据库连接长时间未活动被服务器关闭

解决方案:


设置连接池ping=2(DBUtils参数),定期发送心跳包


运行


pool = PooledDB(creator=pymysql, ping=2, ...)  # ping=2表示每次连接使用前检查有效性

AI写代码

调整 MySQL 服务器配置(wait_timeout参数,默认 8 小时)

9.2 字符集乱码问题

现象:插入中文数据显示为?或乱码

解决方案:


确保数据库、表、字段均使用utf8mb4字符集

连接时显式指定charset=utf8mb4

在 MySQL 配置文件(my.cnf)中全局设置字符集:

ini


[client]

default-character-set = utf8mb4

[mysql]

default-character-set = utf8mb4

[mysqld]

character-set-server = utf8mb4

collation-server = utf8mb4_unicode_ci

AI写代码

十、学习资源与进阶路径

总结

本文系统梳理了 Python 操作 MySQL 数据库的核心知识体系,从基础连接、CRUD 操作到事务管理、连接池优化,再到异步编程与 ORM 集成,覆盖了开发全流程的关键环节。通过实际案例与性能优化策略,帮助读者建立从理论到实践的完整认知。

                        

原文链接:https://blog.csdn.net/2501_91112123/article/details/148188180

栏目分类

联系方式
  • help@yxrjt.cn
  • lgc@yxrjt.cn
  • admin@yxrjt.cn