生成专题页Blog--建立并返回 MySQL 数据库连接

bash 复制代码
def get_db():
    """建立并返回 MySQL 数据库连接(从环境变量获取配置,默认返回 DictCursor 游标)"""
    return pymysql.connect(
        host=get_env('PYTHON_DB_HOST', 'ip'),
        port=int(get_env('PYTHON_DB_PORT', '端口')),
        user=get_env('PYTHON_DB_USERNAME', '用户名'),
        password=get_env('PYTHON_DB_PASSWORD', '密码'),
        database=get_env('PYTHON_DB_DATABASE', '数据库名'),
        cursorclass=pymysql.cursors.DictCursor,  # 查询结果自动封装为 Python 字典
        autocommit=True  # 开启自动提交
    )

作用:从环境变量动态读取数据库配置(包含兜底默认值),建立并返回一个配置好的 PyMySQL 连接对象。

分布拆解方法:

return pymysql.connect()

pymysql.connect() 是 Python 中 PyMySQL 驱动连接 MySQL 数据库的核心方法。它接收一系列配置参数,建立并返回一个数据库连接对象(Connection)。

通常包含以下参数:

bash 复制代码
import pymysql

db_connection = pymysql.connect(
    host='127.0.0.1',             # 数据库服务器地址 (可以是 IP 或域名)
    port=3306,                    # 数据库端口 (整数类型,默认为 3306)
    user='root',                  # 数据库登录用户名
    password='your_password',      # 数据库登录密码
    database='my_db',             # 要连接的数据库名称 (也可以写作 db='my_db')
    charset='utf8mb4',            # 字符集编码 (强烈建议设为 utf8mb4 以支持表情符和全 Emoji)
    cursorclass=pymysql.cursors.DictCursor,  # 指定游标类型 (如:返回字典而非元组)
    autocommit=True,              # 是否开启自动提交 (True/False)
    connect_timeout=10,           # 连接超时时间 (秒)
    ssl={'ssl': ...}              # SSL 加密配置 (可选,用于安全连接)
)

标准生产/开发环境写法(配合环境变量与字典游标)

bash 复制代码
import os
import pymysql

def get_db():
    return pymysql.connect(
        host=os.getenv('DB_HOST', '127.0.0.1'),
        port=int(os.getenv('DB_PORT', 3306)),
        user=os.getenv('DB_USER', 'root'),
        password=os.getenv('DB_PASSWORD', ''),
        database=os.getenv('DB_NAME', 'test_db'),
        charset='utf8mb4',
        cursorclass=pymysql.cursors.DictCursor,  # 查询结果直接返回字典 {'col': val}
        autocommit=True                          # 写操作自动提交,免去手动 commit
    )

pymysql.connect() 返回的对象如何使用?

连接建立后,需要通过连接对象创建游标(Cursor)来执行 SQL:

bash 复制代码
# 1. 获取数据库连接
db = get_db()

# 2. 使用上下文管理器执行 SQL 操作
try:
    with db.cursor() as cursor:
        sql = "SELECT id, title FROM topics WHERE id = %s"
        cursor.execute(sql, (1,))
        result = cursor.fetchone()
        print(result)
finally:
    # 3. 必须及时关闭连接,释放数据库资源
    db.close()

关键注意要点

port 必须是整型(int): 如果端口值是从 os.getenv 或配置文件中读取的字符串(如 '3306'),必须用 int('3306') 转换,否则 PyMySQL 会抛出类型错误。

编码推荐 utf8mb4: 不要使用 'utf8',因为 MySQL 的原生 utf8 是简版(最大 3 字节),遇到 Emoji或某些特殊字符会报错,utf8mb4 是最安全的选择。

资源释放(关闭连接): 长久持有 pymysql.connect() 返回的对象不关闭,会导致 MySQL 的连接池被占满(报错 Toomany connections),务必确保在代码执行完毕后显式调用 db.close(),或在高并发场景下使用连接池(如dbutils)。

host=get_env('PYTHON_DB_HOST', 'ip')...

它的含义是:"优先从系统的环境变量中读取 PYTHON_DB_HOST 的值;如果环境变量里没配置,就默认连接本地的 127.0.0.1"。

一般环境变量在项目根目录的 .env 文件 中定义

在很多 Python 项目中,开发者会在项目根目录下创建一个名为 .env 的文本文件,里面专门用来放环境变量:

bash 复制代码
# .env 文件内容
PYTHON_DB_HOST=127.0.0.1
PYTHON_DB_PORT=3306
PYTHON_DB_USERNAME=root
PYTHON_DB_PASSWORD=your_password

port=int(get_env('PYTHON_DB_PORT', 3306))

为什么一定要套一层 int()?

在操作系统或 .env 文件中,所有的环境变量提取出来时本质上都是"字符串"(比如文本 "3306")。

但 PyMySQL 驱动的 connect() 函数对 port 参数有着严格的数据类型检查:它必须是一个整型数字(int)。

cursorclass=pymysql.cursors.DictCursor

它的含义是:将数据库查询结果的游标(Cursor)类型,指定为"字典游标"(DictCursor)。

默认游标 vs 字典游标(对比说明)

默认情况下(即不加这行配置),PyMySQL 会使用标准的 TupleCursor(元组游标)。

假设你的数据库 products 表里有一行数据:

id=101, name='Leather Jacket', price=99.00

  1. 如果不加这行配置(默认元组游标):
    查询返回的结果是一个纯元组(Tuple),它只保留数据的值,丢失了列名(字段名):
bash 复制代码
cursor.execute("SELECT id, name, price FROM products WHERE id = 101")
row = cursor.fetchone()

print(row) 
# 输出结果: (101, 'Leather Jacket', 99.00)

# 取值时必须记住列的顺序(用下标 0, 1, 2):
product_id = row[0]
product_name = row[1]
  1. 加了 cursorclass=pymysql.cursors.DictCursor(字典游标):
    查询返回的结果会被自动封装为一个 Python 字典(Dictionary),键(Key)就是数据库中的列名/字段名,值(Value)就是数据:
bash 复制代码
cursor.execute("SELECT id, name, price FROM products WHERE id = 101")
row = cursor.fetchone()

print(row)
# 输出结果: {'id': 101, 'name': 'Leather Jacket', 'price': 99.00}

# 取值时可以直接使用字段名:
product_id = row['id']
product_name = row['name']

它的含义是:"开启自动提交模式(Auto-Commit)。只要执行了任何写数据库的操作(如 INSERT、UPDATE、DELETE),MySQL 会立刻把变动持久化保存到磁盘上,不需要你手动编写 db.commit() 代码。"

一、 什么是"事务"与"提交"?

在默认情况下,MySQL 的 InnoDB 存储引擎使用事务(Transaction)保护机制:

当你执行了一句修改命令(比如 INSERT INTO topics ...),数据库其实只是在内存缓冲区/临时事务日志里记了一笔,并没有真正确定保存

只有当你显式执行了 db.commit()(提交),数据库才会把这笔变动正式写入磁盘数据文件。

如果中途报错或者执行了 db.rollback()(回滚),刚才执行的所有更改就会瞬间撤销,仿佛什么都没发生过。

二、 autocommit=True 的实际效果对比

假设我们要插入一条新的专题页数据:

  1. 如果不设置 autocommit=True(默认手动提交):
bash 复制代码
with db.cursor() as cursor:
    cursor.execute("INSERT INTO topics (title) VALUES ('2026热销指南')")

# ⚠️ 必须手动加上这行,数据库里的表才会真正多出这条记录!
# 如果忘了写这行,程序运行结束也不会报错,但数据库里根本没有数据!
db.commit()
  1. 设置了 autocommit=True(开启自动提交):
bash 复制代码
with db.cursor() as cursor:
    # 只要这行代码执行成功,数据库就会【立刻】写入磁盘!
    cursor.execute("INSERT INTO topics (title) VALUES ('2026热销指南')")

# 不需要写 db.commit(),数据已经稳稳存进数据库了!

注意事项

涉及资金、订单等核心业务逻辑时要谨慎使用:

破坏了"多步骤原子性":假设你在做"扣减库存 + 创建订单"的操作:扣减库存成功 →\rightarrow→(由于 autocommit=True,立刻写死到数据库)创建订单失败报错 →\rightarrow→ 崩溃!因为开启了自动提交,步骤 1 已经无法自动回滚了,导致库存扣了却没生成订单。

这种需要"要么全成功,要么全失败"的多表操作,必须把 autocommit 设为 False 并手动控制事务。

相关推荐
ONE_SIX_MIX1 小时前
qwenpaw-plugin-file-tools QwenPaw增强文件工具 更新 v1.1.1
python·qwenpaw
奶糖 肥晨1 小时前
DBeaver 安装与 MySQL 连接配置教程
数据库·mysql
AOwhisky1 小时前
Python 学习笔记(第五期)——组合数据类型:列表、元组、集合与字典精讲——核心知识点自测与详解
开发语言·笔记·python·学习·云计算
万亿少女的梦1681 小时前
基于Spring Boot、Java与MySQL的网络订餐系统设计与实现
java·spring boot·mysql·系统设计·网络订餐
码农学院1 小时前
GEO与SEO协同:从传统搜索到生成式搜索的平滑迁移路径
服务器·前端·python
程序员羽痕1 小时前
基于 Django + PyTorch 的中文字体识别系统
pytorch·python·django
Database_Cool_3 小时前
阿里云 RDS MySQL 降本增效实战:从规格选型到成本优化,月成本降低64%全攻略
mysql·阿里云·云计算
大模型码小白12 小时前
【Python零基础教程】继承、多态与魔法函数:面向对象编程三大核心特性详解
java·大数据·开发语言·人工智能·python·ai编程
麻雀飞吧12 小时前
最新量化学习路径,交易认知和技术实现要并行
人工智能·python