Python库PyMySQL的使用指南

Python库PyMySQL的使用指南

写在前面:这篇文章是我结合PyMySQL官方文档和实际项目经验整理而成的。如果你正在用Python操作MySQL数据库,希望这篇文章能帮你少走一些弯路。


一、背景:为什么需要PyMySQL?

1.1 Python与数据库的故事

做过Web开发的同学都知道,几乎所有的应用都需要和数据库打交道。Python作为一门"优雅"的语言,自然也少不了和MySQL这个"老大哥"配合。

在Python的世界里,连接MySQL主要有这几种选择:

方案 特点 适用场景
MySQLdb 老牌库,C扩展实现,性能好 只支持Python 2,已逐渐淘汰
mysql-connector-python MySQL官方出品,纯Python实现 通用场景,但性能一般
PyMySQL 纯Python实现,兼容MySQLdb接口 Python 3推荐方案
SQLAlchemy ORM框架,底层可选用PyMySQL 大型项目,需要ORM支持

打个比方:如果把Python比作一个厨师,那PyMySQL就是他手里的菜刀------不是最花哨的工具,但绝对是最实用、最顺手的那一把。

1.2 PyMySQL的优势

为什么推荐PyMySQL?简单总结几个关键词:

  • 纯Python实现:不需要编译C扩展,安装简单,跨平台无忧
  • 兼容性好:接口和MySQLdb几乎一样,迁移成本低
  • 活跃维护:GitHub上持续更新,社区活跃
  • Python 3原生支持:专门为Python 3设计和优化

二、问题:我们面临哪些挑战?

在实际开发中,操作数据库经常会遇到这些问题:

2.1 连接管理

python 复制代码
# 这样的代码你是不是很熟悉?
conn = pymysql.connect(host='localhost', user='root', password='123456')
cursor = conn.cursor()
cursor.execute("SELECT * FROM users")
data = cursor.fetchall()
# 如果这里抛异常了,conn和cursor就泄漏了...
cursor.close()
conn.close()

问题:手动管理连接容易忘记关闭,导致连接泄漏。

2.2 SQL注入风险

python 复制代码
# 危险写法:字符串拼接
name = request.GET['name']
sql = f"SELECT * FROM users WHERE name = '{name}'"
# 如果name是 "'; DROP TABLE users; --",后果不堪设想

问题:直接拼接SQL字符串,容易被SQL注入攻击。

2.3 事务处理

python 复制代码
# 转账场景:A给B转100元
cursor.execute("UPDATE accounts SET balance = balance - 100 WHERE id = 1")
# 如果这里程序崩溃了,A的钱扣了,B的钱没加...
cursor.execute("UPDATE accounts SET balance = balance + 100 WHERE id = 2")
conn.commit()

问题:没有正确的事务管理,数据一致性无法保证。


三、方案:PyMySQL如何解决这些问题?

3.1 安装PyMySQL

先说安装,非常简单:

bash 复制代码
# 方式一:直接安装
pip install PyMySQL

# 方式二:指定版本安装
pip install PyMySQL==1.1.0

# 方式三:使用国内镜像(推荐,速度快)
pip install PyMySQL -i https://pypi.tuna.tsinghua.edu.cn/simple

环境要求

  • Python 3.7+
  • MySQL 5.7+ 或 MariaDB 10.2+

安装完成后,验证一下:

python 复制代码
import pymysql
print(pymysql.__version__)  # 输出版本号,说明安装成功

3.2 核心概念:连接与游标

在开始写代码之前,先理解两个核心概念:

连接(Connection):就像是你和数据库之间的一条电话线。你需要先拨通电话(建立连接),才能和数据库"对话"。

游标(Cursor):就像是你在对话中使用的"遥控器"。你通过游标发送指令(执行SQL),获取结果(fetch数据)。

复制代码
┌─────────────┐      ┌─────────────┐      ┌─────────────┐
│   Python    │ ───> │  Connection │ ───> │    MySQL    │
│   程序      │ <─── │   (连接)    │ <─── │   数据库    │
└─────────────┘      └─────────────┘      └─────────────┘
       │
       │ 使用
       ▼
┌─────────────┐
│   Cursor    │
│   (游标)    │
└─────────────┘

四、实现:从入门到实战

4.1 建立数据库连接

基础版

python 复制代码
import pymysql

# 建立连接
connection = pymysql.connect(
    host='localhost',        # 数据库地址
    port=3306,              # 端口号,默认3306
    user='root',            # 用户名
    password='your_password', # 密码
    database='test_db',     # 数据库名
    charset='utf8mb4'       # 字符编码,推荐utf8mb4支持emoji
)

print("连接成功!")
connection.close()

推荐版(使用上下文管理器)

python 复制代码
import pymysql

# 使用 with 语句,自动管理连接的关闭
with pymysql.connect(
    host='localhost',
    user='root',
    password='your_password',
    database='test_db',
    charset='utf8mb4'
) as connection:
    with connection.cursor() as cursor:
        cursor.execute("SELECT VERSION()")
        version = cursor.fetchone()
        print(f"MySQL版本: {version[0]}")
# 离开 with 块后,连接自动关闭

为什么推荐 with 语句? 就像你用完水龙头要关掉一样,with 语句保证了即使代码出错,连接也会被正确关闭。

4.2 查询数据

基础查询

python 复制代码
import pymysql

with pymysql.connect(
    host='localhost',
    user='root',
    password='your_password',
    database='test_db',
    charset='utf8mb4'
) as conn:
    with conn.cursor() as cursor:
        # 执行查询
        cursor.execute("SELECT id, name, email FROM users")

        # 获取一条记录
        one_row = cursor.fetchone()
        print(f"单条记录: {one_row}")

        # 获取所有记录
        all_rows = cursor.fetchall()
        for row in all_rows:
            print(f"ID: {row[0]}, 姓名: {row[1]}, 邮箱: {row[2]}")

使用DictCursor(推荐)

python 复制代码
import pymysql
from pymysql.cursors import DictCursor

with pymysql.connect(
    host='localhost',
    user='root',
    password='your_password',
    database='test_db',
    charset='utf8mb4',
    cursorclass=DictCursor  # 设置游标类型为字典
) as conn:
    with conn.cursor() as cursor:
        cursor.execute("SELECT id, name, email FROM users")
        users = cursor.fetchall()

        for user in users:
            # 返回的是字典,用键名访问,更直观
            print(f"ID: {user['id']}, 姓名: {user['name']}, 邮箱: {user['email']}")

小贴士 :使用 DictCursor 后,返回的数据是字典格式,用 user['name']user[1] 更易读,代码可维护性更好。

4.3 插入数据

单条插入

python 复制代码
import pymysql
from pymysql.cursors import DictCursor

with pymysql.connect(
    host='localhost',
    user='root',
    password='your_password',
    database='test_db',
    charset='utf8mb4'
) as conn:
    with conn.cursor() as cursor:
        # 使用参数化查询,防止SQL注入
        sql = "INSERT INTO users (name, email, age) VALUES (%s, %s, %s)"
        cursor.execute(sql, ('张三', 'zhangsan@example.com', 25))

    # 提交事务
    conn.commit()
    print(f"插入成功,影响行数: {cursor.rowcount}")

批量插入

python 复制代码
import pymysql

with pymysql.connect(
    host='localhost',
    user='root',
    password='your_password',
    database='test_db',
    charset='utf8mb4'
) as conn:
    with conn.cursor() as cursor:
        # 准备批量数据
        users_data = [
            ('李四', 'lisi@example.com', 28),
            ('王五', 'wangwu@example.com', 32),
            ('赵六', 'zhaoliu@example.com', 24),
            ('孙七', 'sunqi@example.com', 29),
        ]

        # 使用 executemany 批量插入
        sql = "INSERT INTO users (name, email, age) VALUES (%s, %s, %s)"
        affected_rows = cursor.executemany(sql, users_data)

    conn.commit()
    print(f"批量插入成功,影响行数: {affected_rows}")

4.4 更新和删除

更新数据

python 复制代码
import pymysql

with pymysql.connect(
    host='localhost',
    user='root',
    password='your_password',
    database='test_db',
    charset='utf8mb4'
) as conn:
    with conn.cursor() as cursor:
        # 更新用户年龄
        sql = "UPDATE users SET age = %s WHERE name = %s"
        cursor.execute(sql, (26, '张三'))

    conn.commit()
    print(f"更新成功,影响行数: {cursor.rowcount}")

删除数据

python 复制代码
import pymysql

with pymysql.connect(
    host='localhost',
    user='root',
    password='your_password',
    database='test_db',
    charset='utf8mb4'
) as conn:
    with conn.cursor() as cursor:
        # 删除指定用户
        sql = "DELETE FROM users WHERE name = %s"
        cursor.execute(sql, ('张三',))

    conn.commit()
    print(f"删除成功,影响行数: {cursor.rowcount}")

4.5 事务管理(重要!)

场景:银行转账,A给B转100元

python 复制代码
import pymysql
from pymysql import MySQLError

def transfer_money(from_id, to_id, amount):
    """转账函数:保证数据一致性"""
    with pymysql.connect(
        host='localhost',
        user='root',
        password='your_password',
        database='test_db',
        charset='utf8mb4'
    ) as conn:
        try:
            with conn.cursor() as cursor:
                # 第一步:检查余额
                cursor.execute("SELECT balance FROM accounts WHERE id = %s", (from_id,))
                result = cursor.fetchone()
                if not result or result[0] < amount:
                    print("余额不足!")
                    return False

                # 第二步:从A账户扣款
                cursor.execute(
                    "UPDATE accounts SET balance = balance - %s WHERE id = %s",
                    (amount, from_id)
                )

                # 第三步:给B账户加款
                cursor.execute(
                    "UPDATE accounts SET balance = balance + %s WHERE id = %s",
                    (amount, to_id)
                )

            # 提交事务
            conn.commit()
            print(f"转账成功:{from_id} -> {to_id},金额:{amount}")
            return True

        except MySQLError as e:
            # 发生错误,回滚事务
            conn.rollback()
            print(f"转账失败,已回滚: {e}")
            return False

# 使用示例
transfer_money(from_id=1, to_id=2, amount=100)

事务的ACID特性

  • 原子性(Atomicity):要么全部成功,要么全部失败
  • 一致性(Consistency):事务前后数据保持一致
  • 隔离性(Isolation):多个事务互不干扰
  • 持久性(Durability):提交后数据永久保存

4.6 参数化查询(防SQL注入)

错误示范

python 复制代码
# ❌ 危险!字符串拼接
name = "'; DROP TABLE users; --"
sql = f"SELECT * FROM users WHERE name = '{name}'"
# 执行结果:SELECT * FROM users WHERE name = ''; DROP TABLE users; --'
# 后果:users表被删除!

正确做法

python 复制代码
# ✅ 安全!参数化查询
name = "'; DROP TABLE users; --"
sql = "SELECT * FROM users WHERE name = %s"
cursor.execute(sql, (name,))
# PyMySQL会自动转义特殊字符,SQL注入无法生效

记住:永远不要用字符串拼接来构建SQL语句!参数化查询是你的"护身符"。

4.7 游标类型详解

PyMySQL提供了多种游标类型,适用于不同场景:

python 复制代码
import pymysql
from pymysql.cursors import (
    Cursor,           # 默认游标,返回元组
    DictCursor,       # 字典游标,返回字典
    SSCursor,         # 服务端游标,适合大数据量
    SSDictCursor      # 服务端字典游标
)

# 1. 默认游标 - 返回元组
with pymysql.connect(host='localhost', user='root', password='pwd', database='test') as conn:
    with conn.cursor() as cursor:
        cursor.execute("SELECT * FROM users")
        row = cursor.fetchone()
        print(row)  # (1, '张三', 'zhangsan@example.com')

# 2. 字典游标 - 返回字典(推荐)
with pymysql.connect(host='localhost', user='root', password='pwd', database='test',
                     cursorclass=DictCursor) as conn:
    with conn.cursor() as cursor:
        cursor.execute("SELECT * FROM users")
        row = cursor.fetchone()
        print(row)  # {'id': 1, 'name': '张三', 'email': 'zhangsan@example.com'}

# 3. 服务端游标 - 适合处理大量数据
with pymysql.connect(host='localhost', user='root', password='pwd', database='test') as conn:
    with conn.cursor(SSCursor) as cursor:
        cursor.execute("SELECT * FROM large_table")
        for row in cursor:  # 逐行读取,不会一次性加载到内存
            process(row)

五、进阶:生产环境最佳实践

5.1 连接池配置

在生产环境中,频繁创建和销毁连接是很耗资源的。使用连接池可以显著提升性能:

python 复制代码
from dbutils.pooled_db import PooledDB
import pymysql

# 创建连接池
pool = PooledDB(
    creator=pymysql,           # 使用PyMySQL作为连接创建者
    maxconnections=20,         # 最大连接数
    mincached=5,               # 初始化时创建的最小连接数
    maxcached=10,              # 最大空闲连接数
    blocking=True,             # 连接池满时是否阻塞等待
    maxusage=None,             # 单个连接的最大复用次数
    setsession=[],             # 开始会话前执行的命令
    ping=0,                    # ping MySQL服务端,0=不ping

    # 数据库连接参数
    host='localhost',
    port=3306,
    user='root',
    password='your_password',
    database='test_db',
    charset='utf8mb4'
)

def get_user_by_id(user_id):
    """从连接池获取连接查询用户"""
    conn = pool.connection()  # 从池中获取连接
    try:
        with conn.cursor(pymysql.cursors.DictCursor) as cursor:
            cursor.execute("SELECT * FROM users WHERE id = %s", (user_id,))
            return cursor.fetchone()
    finally:
        conn.close()  # 连接归还到池中,而非真正关闭

# 使用
user = get_user_by_id(1)
print(user)

连接池参数说明

参数 说明 推荐值
maxconnections 最大连接数 根据并发量设置,一般10-50
mincached 最小空闲连接 2-5
maxcached 最大空闲连接 5-10
blocking 池满时是否阻塞 True(避免连接失败)

5.2 超时配置

python 复制代码
import pymysql

connection = pymysql.connect(
    host='localhost',
    user='root',
    password='your_password',
    database='test_db',

    # 超时配置(单位:秒)
    connect_timeout=10,    # 连接超时
    read_timeout=30,       # 读取超时
    write_timeout=30,      # 写入超时

    # 自动提交(根据需求设置)
    autocommit=False,      # False表示手动管理事务

    charset='utf8mb4'
)

5.3 异常处理

python 复制代码
import pymysql
from pymysql import MySQLError
from pymysql.err import (
    OperationalError,    # 连接错误
    ProgrammingError,    # SQL语法错误
    IntegrityError,      # 数据完整性错误
    DataError,           # 数据错误
    NotSupportedError    # 不支持的操作
)

def safe_query(sql, params=None):
    """安全的查询函数,包含完善的异常处理"""
    try:
        with pymysql.connect(
            host='localhost',
            user='root',
            password='your_password',
            database='test_db',
            charset='utf8mb4'
        ) as conn:
            with conn.cursor(pymysql.cursors.DictCursor) as cursor:
                cursor.execute(sql, params)
                return cursor.fetchall()

    except OperationalError as e:
        print(f"数据库连接错误: {e}")
        # 可以在这里实现重连逻辑
        return None

    except ProgrammingError as e:
        print(f"SQL语法错误: {e}")
        return None

    except IntegrityError as e:
        print(f"数据完整性错误(如主键冲突): {e}")
        return None

    except DataError as e:
        print(f"数据错误(如字段长度超限): {e}")
        return None

    except MySQLError as e:
        print(f"其他数据库错误: {e}")
        return None

    except Exception as e:
        print(f"未知错误: {e}")
        return None

# 使用示例
users = safe_query("SELECT * FROM users WHERE age > %s", (25,))
if users:
    for user in users:
        print(user)

5.4 封装数据库工具类

将常用操作封装成工具类,提高代码复用性:

python 复制代码
import pymysql
from pymysql.cursors import DictCursor
from contextlib import contextmanager

class MySQLHelper:
    """MySQL数据库操作助手类"""

    def __init__(self, host='localhost', port=3306, user='root',
                 password='', database='', charset='utf8mb4'):
        self.config = {
            'host': host,
            'port': port,
            'user': user,
            'password': password,
            'database': database,
            'charset': charset,
            'cursorclass': DictCursor
        }

    @contextmanager
    def get_connection(self):
        """获取数据库连接的上下文管理器"""
        conn = pymysql.connect(**self.config)
        try:
            yield conn
        finally:
            conn.close()

    def query(self, sql, params=None):
        """执行查询语句,返回结果列表"""
        with self.get_connection() as conn:
            with conn.cursor() as cursor:
                cursor.execute(sql, params)
                return cursor.fetchall()

    def query_one(self, sql, params=None):
        """执行查询语句,返回单条结果"""
        with self.get_connection() as conn:
            with conn.cursor() as cursor:
                cursor.execute(sql, params)
                return cursor.fetchone()

    def execute(self, sql, params=None):
        """执行增删改语句,返回影响行数"""
        with self.get_connection() as conn:
            with conn.cursor() as cursor:
                result = cursor.execute(sql, params)
            conn.commit()
            return result

    def execute_many(self, sql, params_list):
        """批量执行增删改语句,返回影响行数"""
        with self.get_connection() as conn:
            with conn.cursor() as cursor:
                result = cursor.executemany(sql, params_list)
            conn.commit()
            return result

    def execute_with_transaction(self, operations):
        """在事务中执行多个操作

        Args:
            operations: 一个列表,每个元素是 (sql, params) 元组
        """
        with self.get_connection() as conn:
            try:
                with conn.cursor() as cursor:
                    for sql, params in operations:
                        cursor.execute(sql, params)
                conn.commit()
                return True
            except Exception as e:
                conn.rollback()
                print(f"事务执行失败: {e}")
                return False


# 使用示例
if __name__ == '__main__':
    db = MySQLHelper(
        host='localhost',
        user='root',
        password='your_password',
        database='test_db'
    )

    # 查询所有用户
    users = db.query("SELECT * FROM users")
    print(f"用户列表: {users}")

    # 查询单个用户
    user = db.query_one("SELECT * FROM users WHERE id = %s", (1,))
    print(f"用户详情: {user}")

    # 插入数据
    affected = db.execute(
        "INSERT INTO users (name, email) VALUES (%s, %s)",
        ('新用户', 'new@example.com')
    )
    print(f"插入了 {affected} 条记录")

    # 事务操作
    operations = [
        ("UPDATE accounts SET balance = balance - 100 WHERE id = %s", (1,)),
        ("UPDATE accounts SET balance = balance + 100 WHERE id = %s", (2,)),
    ]
    success = db.execute_with_transaction(operations)
    print(f"事务{'成功' if success else '失败'}")

六、结果:完整的实战案例

6.1 用户管理系统

下面是一个完整的用户管理系统的示例:

python 复制代码
"""
用户管理系统 - 完整示例
演示PyMySQL在实际项目中的使用
"""

import pymysql
from pymysql.cursors import DictCursor
from datetime import datetime


class UserManager:
    """用户管理类"""

    def __init__(self, db_config):
        self.db_config = db_config

    def _get_connection(self):
        """获取数据库连接"""
        return pymysql.connect(**self.db_config, cursorclass=DictCursor)

    def init_db(self):
        """初始化数据库表"""
        with self._get_connection() as conn:
            with conn.cursor() as cursor:
                cursor.execute("""
                    CREATE TABLE IF NOT EXISTS users (
                        id INT AUTO_INCREMENT PRIMARY KEY,
                        name VARCHAR(100) NOT NULL,
                        email VARCHAR(200) UNIQUE NOT NULL,
                        age INT,
                        created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
                        updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
                    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
                """)
            conn.commit()
            print("数据库表初始化完成")

    def create_user(self, name, email, age=None):
        """创建用户"""
        with self._get_connection() as conn:
            with conn.cursor() as cursor:
                sql = "INSERT INTO users (name, email, age) VALUES (%s, %s, %s)"
                cursor.execute(sql, (name, email, age))
            conn.commit()
            return cursor.lastrowid

    def get_user(self, user_id):
        """获取用户信息"""
        with self._get_connection() as conn:
            with conn.cursor() as cursor:
                cursor.execute("SELECT * FROM users WHERE id = %s", (user_id,))
                return cursor.fetchone()

    def get_all_users(self, page=1, page_size=10):
        """分页获取所有用户"""
        offset = (page - 1) * page_size
        with self._get_connection() as conn:
            with conn.cursor() as cursor:
                # 获取总数
                cursor.execute("SELECT COUNT(*) as total FROM users")
                total = cursor.fetchone()['total']

                # 获取分页数据
                cursor.execute(
                    "SELECT * FROM users ORDER BY id DESC LIMIT %s OFFSET %s",
                    (page_size, offset)
                )
                users = cursor.fetchall()

                return {
                    'total': total,
                    'page': page,
                    'page_size': page_size,
                    'data': users
                }

    def update_user(self, user_id, **kwargs):
        """更新用户信息"""
        if not kwargs:
            return 0

        # 构建更新语句
        set_clause = ', '.join([f"{k} = %s" for k in kwargs.keys()])
        values = list(kwargs.values())
        values.append(user_id)

        with self._get_connection() as conn:
            with conn.cursor() as cursor:
                sql = f"UPDATE users SET {set_clause} WHERE id = %s"
                cursor.execute(sql, values)
            conn.commit()
            return cursor.rowcount

    def delete_user(self, user_id):
        """删除用户"""
        with self._get_connection() as conn:
            with conn.cursor() as cursor:
                cursor.execute("DELETE FROM users WHERE id = %s", (user_id,))
            conn.commit()
            return cursor.rowcount

    def search_users(self, keyword):
        """搜索用户"""
        with self._get_connection() as conn:
            with conn.cursor() as cursor:
                sql = """
                    SELECT * FROM users
                    WHERE name LIKE %s OR email LIKE %s
                """
                like_keyword = f"%{keyword}%"
                cursor.execute(sql, (like_keyword, like_keyword))
                return cursor.fetchall()

    def batch_create_users(self, users_data):
        """批量创建用户"""
        with self._get_connection() as conn:
            with conn.cursor() as cursor:
                sql = "INSERT INTO users (name, email, age) VALUES (%s, %s, %s)"
                affected = cursor.executemany(sql, users_data)
            conn.commit()
            return affected


# 使用示例
if __name__ == '__main__':
    # 数据库配置
    db_config = {
        'host': 'localhost',
        'port': 3306,
        'user': 'root',
        'password': 'your_password',
        'database': 'test_db',
        'charset': 'utf8mb4'
    }

    # 创建用户管理器实例
    manager = UserManager(db_config)

    # 初始化数据库
    manager.init_db()

    # 创建用户
    user_id = manager.create_user('张三', 'zhangsan@example.com', 25)
    print(f"创建用户成功,ID: {user_id}")

    # 获取用户
    user = manager.get_user(user_id)
    print(f"用户信息: {user}")

    # 更新用户
    affected = manager.update_user(user_id, name='张三丰', age=30)
    print(f"更新了 {affected} 条记录")

    # 分页查询
    result = manager.get_all_users(page=1, page_size=5)
    print(f"共 {result['total']} 个用户,当前页: {result['data']}")

    # 搜索用户
    users = manager.search_users('张')
    print(f"搜索结果: {users}")

    # 批量创建
    batch_data = [
        ('李四', 'lisi@example.com', 28),
        ('王五', 'wangwu@example.com', 32),
        ('赵六', 'zhaoliu@example.com', 24),
    ]
    affected = manager.batch_create_users(batch_data)
    print(f"批量创建了 {affected} 个用户")

七、总结与延伸阅读

7.1 核心要点回顾

要点 说明
使用 with 语句 自动管理连接和游标的生命周期
参数化查询 永远不要拼接SQL字符串,防止SQL注入
事务管理 涉及多表操作时,使用事务保证数据一致性
DictCursor 使用字典游标,代码更易读
连接池 生产环境使用连接池提升性能
异常处理 完善的异常处理,避免程序崩溃

7.2 常见问题FAQ

Q1: PyMySQL和mysql-connector-python选哪个?

A: 如果你追求简单易用和兼容性,选PyMySQL;如果你需要MySQL官方支持,选mysql-connector-python。两者功能相似,性能差异不大。

Q2: 出现 "ModuleNotFoundError: No module named 'pymysql'" 怎么办?

A: 检查是否安装了PyMySQL:

bash 复制代码
pip install PyMySQL

如果使用虚拟环境,确保在正确的虚拟环境中安装。

Q3: 连接数据库时报错 "Access denied" 怎么办?

A: 检查以下几点:

  1. 用户名和密码是否正确
  2. 用户是否有访问指定数据库的权限
  3. MySQL服务是否允许远程连接(如果是远程访问)

Q4: 中文乱码怎么解决?

A: 确保连接时设置 charset='utf8mb4',同时数据库和表的编码也要设置为 utf8mb4

7.3 性能优化建议

  1. 使用连接池:避免频繁创建和销毁连接
  2. 批量操作 :使用 executemany 而不是循环执行 execute
  3. 合理使用索引:为经常查询的字段添加索引
  4. 分页查询 :大数据量使用 LIMIT 分页,避免一次性加载
  5. 服务端游标 :处理大数据集时使用 SSCursor

7.4 延伸阅读

7.5 写在最后

PyMySQL是一个小而美的库,它没有ORM框架那么"高大上",但胜在简单、直接、高效。对于大多数中小型项目来说,PyMySQL完全够用。

记住几个关键原则:

  1. 安全第一:永远使用参数化查询
  2. 资源管理 :用 with 语句管理连接
  3. 事务意识:涉及多表操作时,记得用事务
  4. 性能优化:生产环境使用连接池

希望这篇文章对你有帮助。如果你有任何问题或建议,欢迎交流讨论!


作者的话:技术文章的价值在于分享和帮助他人成长。如果这篇文章帮你解决了问题,或者让你学到了新知识,那我的目的就达到了。祝你编程愉快!

相关推荐
z落落9 小时前
C# 泛型方法(原理、类型推断、多泛型参数)+泛型效率(普通类型 VS Object装箱 VS 泛型)
开发语言·c#
L_09079 小时前
【C++】异常
开发语言·c++
世辰辰辰10 小时前
批量修改图片/文本名子
开发语言·python·批量修改文件名
myenjoy_111 小时前
MQTT 与 Sparkplug B——从车间到云端的最后一公里
网络·python
z落落11 小时前
C# 四种特殊类:抽象类、密封类、静态类、部分类
开发语言·c#
VidDown12 小时前
Webhook 调试器:让第三方回调“原形毕露”
java·开发语言·javascript·编辑器·postman
装不满的克莱因瓶12 小时前
基于 OpenResty 扩展开发实现动态服务注册与发现能力
java·开发语言·架构·openresty
颜酱12 小时前
LangChain 输出解析器:把模型回复变成你要的数据
python·langchain
2401_8734794013 小时前
企业安全运营中,如何用IP离线库提前发现失陷主机?三步实现风险画像
网络·数据库·python·tcp/ip·ip