悠闲人家·家园-www.yxrjy.cn

学习随记

Python操作MySQL数据库

2025-09-24 10:02 214 浏览

一、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

分享:
相关内容