Python操作MySQL的最全使用教程
前言先说一个不成立的说法「Python 内置了 MySQL 支持」。标准库里跟数据库沾边的模块只有sqlite3内置的嵌入式数据库引擎和dbm一类的键值存储MySQL 驱动一律要额外安装纯 Python 实现和 C 扩展实现都一样。第二个常见的混淆是把驱动driver和 ORM对象关系映射Object-Relational Mapping当成一回事。驱动负责按 MySQL 的线协议连上服务器、把 SQL 发过去、把结果取回来ORM 负责把数据表和 Python 类互相映射。ORM 底下一定还压着一个驱动。这一层分清楚选型才不乱。这两个误解决定了本文的写法先讲清主流驱动各自站在什么位置再讲它们共同遵守的契约——DB-API 2.0PEP 249最后落到事务语义、结果集处理与连接池。本文不逐条演示增删改查目标是让你读完能判断换个驱动哪些代码不用动、哪些必须改。另外网上大量 MySQL 教程还是 Python 2 时代的产物。Python 2.7 已于 2020 年 1 月 1 日停止维护那些print ...语句形式、dict.iteritems()、xrange在 Python 3 下都已失效。一、驱动全景与选型驱动导入名实现方式定位与取舍PyMySQLpymysql纯 Python无编译环境、脚本、教学跨平台一致代价是纯 Python 带来的额外开销mysqlclientMySQLdbC 扩展本机有 C 编译工具链与 MySQL 开发库时可用很多老代码依赖import MySQLdbmysql-connector-pythonmysql.connectorOracle 官方维护、自包含想和官方生态对齐自带连接池另有可选的 C 扩展SQLAlchemysqlalchemy工具层 / ORM不是驱动必须搭配上面任一个要模型映射、要跨库切换时用asyncmyasyncmyCython 实现的 asyncio 驱动asyncio 栈Windows 上编译扩展需要 C 构建工具aiomysqlaiomysql复用 PyMySQL 的 asyncio 驱动asyncio 栈API 形态接近 PyMySQL需要特别说明的是前四个是同步驱动都对外声明遵循 DB-API 2.0asyncmy 和 aiomysql 是异步驱动连接、执行、取结果都要await不在 PEP 249 的那份同步契约之内。二、DB-API 2.0同步驱动共有的契约PEP 249 解决的问题是同步驱动实现各不相同但对外暴露的名字和语义是一份约定。只要驱动声明自己合规换驱动时大部分调用代码就能原样保留。规范要求模块级必须有三个常量apilevel——支持的接口级别只允许1.0或2.0。threadsafety——0 表示线程间不能共享模块1 表示可共享模块但不能共享连接2 表示模块和连接都可共享3 表示模块、连接、游标都可共享。paramstyle——SQL 文本里的占位符风格。paramstyle是迁移时最要命的一个它决定 SQL 文本长什么样值形式例子qmark问号... WHERE name?numeric数字位置... WHERE name:1named命名... WHERE name:nameformatANSI C printf 风格... WHERE name%spyformatPython 扩展风格... WHERE name%(name)s各驱动实际声明的值如下可用驱动名.paramstyle读出核对驱动apilevelthreadsafetyparamstylePyMySQL2.01pyformatmysqlclientMySQLdb2.01formatmysql-connector-python2.01pyformat标准库sqlite3对照用2.0随底层构建而变qmark注意pyformat是format的超集声明pyformat的驱动既接受%s参数传序列也接受%(name)s参数传映射而声明format的驱动只承诺%s。这是跨驱动迁移时最容易踩的一处。连接对象必须提供的方法只有四个close()、commit()、rollback()、cursor()。游标对象必须提供execute(operation[, parameters])、executemany(operation, seq_of_parameters)、fetchone()、fetchmany([size])、fetchall()、close()以及只读属性rowcount、description和可读写属性arraysize默认1fetchmany()不带参数时就按它取行。用标准库的sqlite3可以离线验证这套公共契约——它同样是 DB-API 2.0 实现但不需要数据库服务器# 适用于 Python 3.8import sqlite3conn sqlite3.connect(:memory:)cur conn.cursor()cur.execute(CREATE TABLE t (id INTEGER PRIMARY KEY, name TEXT))cur.executemany(INSERT INTO t (name) VALUES (?), [(a,), (b,), (c,)])conn.commit()cur.execute(SELECT id, name FROM t ORDER BY id)print(rowcount:, cur.rowcount) # 规范允许为 -1表示「无法确定」print(fetchone:, cur.fetchone())print(fetchmany(2):, cur.fetchmany(2))print(fetchall:, cur.fetchall()) # 前面已经取完这里是空列表conn.close()这些名字都是 PEP 249 的公共接口换到 PyMySQL 上完全一样唯一要动的是占位符?改成%s。那么「换驱动」到底要改什么代码换驱动后connect(...)的调用必须改规范明说连接参数是「数据库相关」的不做规定SQL 文本里的占位符必须改由paramstyle决定%s与?不通用依赖驱动私有异常码的分支可能要改公共异常树一致私有错误码与子类名不一定有cur.lastrowid、conn.autocommit等不保证存在属于可选扩展用之前先确认cursor()/execute()/fetch*()/commit()/rollback()/close()不用改它们是规范的核心同一件事不同驱动怎么写把上表落到代码上真正会绊住迁移的是 SQL 文本本身Python 侧的调用形状是一样的。# 适用于 Python 3.8# 同一个查询两种 paramstyle —— 变的只有 SQL 文本# sqlite3: cur.execute(SELECT id, name FROM metrics WHERE score ?, (60,))# pymysql: cur.execute(SELECT id, name FROM metrics WHERE score %s, (60,))# pyformat 驱动还接受命名占位符参数传映射下面两行等价# cur.execute(SELECT id, name FROM metrics WHERE name %s, (cpu,))# cur.execute(SELECT id, name FROM metrics WHERE name %(name)s, {name: cpu})# 连接构造也是同一个形状但参数名不统一跨驱动得逐个查文档# pymysql.connect(host127.0.0.1, userapp, passwordpwd, databasedemo)# MySQLdb.connect(host127.0.0.1, userapp, passwdpwd, dbdemo)# mysql.connector.connect(host127.0.0.1, userapp, passwordpwd, databasedemo)参数名不是公约mysqlclient 沿用的是passwd/db这两个老名字换成另外两家就得改回password/database。三、事务隔离级别与提交语义PEP 249 对提交的要求非常直接.commit()提交任何待处理的事务并且如果数据库支持自动提交接口的初始状态必须是关闭自动提交。这就是「为什么 DB-API 非要你显式commit()」的根源——手动提交是规范定的默认值不是某个驱动的脾气。配套的两条规则同样写在规范里。一是.close()时若还有未提交的修改会触发隐式回滚——「没 commit 就直接关连接」不会报错但改动作废而且这个兜底行为不能依赖驱动和配置不同结果可能不一样。二是.rollback()在规范里标为可选不支持事务的数据库可以不实现它此时调用可能抛NotSupportedError。Connection.autocommit属于可选扩展读到True表示连接处在自动提交非事务模式。但 PEP 249 给了一条弃用提示——通过写这个属性切换模式已被弃用理由是写属性可能触发 I/O 及相关异常在异步环境里很难实现要开自动提交优先用建立连接时的构造参数。接下来是隔离级别。它和commit/rollback不在一个层次前者管「别的连接能看见你的什么」后者管「你自己的修改什么时候生效、什么时候撤销」。而且隔离级别是数据库层面的概念DB-API 不规定——驱动只负责把 SQL 发过去-- 隔离级别在会话/服务器层设置与用哪个 Python 驱动无关SET TRANSACTION ISOLATION LEVEL READ COMMITTED;MySQL 的 InnoDB 支持标准的四档隔离级别隔离级别脏读不可重复读幻读READ UNCOMMITTED可能可能可能READ COMMITTED不会可能可能REPEATABLE READ不会不会标准定义下可能SERIALIZABLE不会不会不会REPEATABLE READ是 InnoDB 的默认隔离级别MySQL 在这一档上额外用 next-key 锁抑制幻读效果比标准定义的底线更强。但「默认级别是哪个」随数据库和版本而变不要拿驱动文档去推断隔离级别去查目标数据库的文档。四、结果集、连接池与生产实践批量结果集executemany 与流式读取批量写用executemany(operation, seq_of_parameters)。规范允许驱动用「多次 execute」或「数组操作一次性提交」来实现两种都合规但规范明确写了这个方法的返回值未定义不要拿它当「插入了 N 行」的依据。对会产生结果集的语句调用executemany也属于未定义行为。读大结果集时别一次fetchall()全塞进内存。规范给出的通用工具是arraysize配fetchmany()arraysize决定fetchmany()不带参数时每次取多少行默认是1。# 适用于 Python 3.8import sqlite3conn sqlite3.connect(:memory:)cur conn.cursor()cur.execute(CREATE TABLE sample (id INTEGER PRIMARY KEY, val TEXT))cur.executemany(INSERT INTO sample (val) VALUES (?),[(fv{i},) for i in range(5)],)conn.commit()cur.arraysize 2 # 让下面不带参数的 fetchmany() 每次取 2 行cur.execute(SELECT id, val FROM sample ORDER BY id)while True:batch cur.fetchmany() # 不传 size就按 arraysize 取if not batch: # 取空了就是读完breakprint(batch)conn.close()除了规范里的arraysize各驱动还会提供服务端流式游标作为扩展。以 PyMySQL 为例pymysql.cursors.SSCursor以及返回字典的SSDictCursor是未缓冲游标按需从服务器拉行客户端内存占用可控。局限也很明确MySQL 协议不回传总行数只能遍历到底才知道有多少行不能向后滚动并且在结果集读完之前这个连接不能执行其他语句——流式读和写要用两条连接。连接池与连接生命周期不要一请求一连接。建立连接要经历握手、认证、会话初始化成本远高于执行一条语句。生产上要用连接池复用场景现成的池mysql-connector-python自带MySQLConnectionPoolSQLAlchemy 的Engine自带连接池如QueuePool由它统一管理asyncioasyncmy / aiomysql各自的create_pool()同样是await获取连接PyMySQL本身不带池需要搭配 SQLAlchemy、DBUtils 之类的工具连接生命周期有两件事要盯。一是空闲连接会被服务端踢掉MySQL 有wait_timeout长时间不用的连接由服务端关闭PyMySQL 提供ping(reconnectTrue)在取用前探活但重连会丢掉未提交的事务所以只能在事务开始之前调用。二是必须设连接超时不设的话网络不通时会长时间阻塞表现为「程序卡住」而不是报错。其余生产事项权限最小化应用账号只授予业务真正需要的权限不要用root凭据外置密码走环境变量或受控配置文件字符集对齐MySQL 的utf8是「最多 3 字节」的历史遗留别名存不了 emoji 和部分生僻字连接和表都用utf8mb4避免SELECT *把 TEXT、BLOB 这类大字段一起拖回来WHERE上常过滤的列建索引并用EXPLAIN看实际执行计划而不是靠猜。常见坑点1. 把驱动和 ORM 当一回事❌ 装完pip install SQLAlchemy就create_engine(mysql://...)—— 引擎底下没有驱动起不来。✅ 先装一个 DBAPI 驱动再在 URL 里同时指明方言和驱动形如mysqlpymysql://...。2. 换驱动只换 import不改占位符❌ 从声明format的驱动换到声明qmark的驱动SQL 里的%s一个字没改 —— 报错或匹配不到数据。✅ 先读目标驱动的paramstyle再逐条替换 SQL 文本里的占位符。3. 用某个驱动的私有异常类兜住所有错误❌ 只写except ...OperationalError:就当成全部错误 —— 唯一键冲突那类错误走的是别的分支会被漏掉。✅ 按 PEP 249 的公共异常树分层捕获DatabaseError之下再分IntegrityError、ProgrammingError、OperationalError等语义各不相同。4. 以为close()等于保存❌ 一批写操作执行完直接conn.close()以为和commit()等价 —— 规范规定未提交就关闭会隐式回滚。✅ 写操作后显式commit()异常路径rollback()close()只负责释放连接。5. 把隔离级别的锅甩给驱动❌ 出现不可重复读就去换驱动或改autocommit—— 隔离级别在数据库会话层换驱动不改它。✅ 先确认当前会话的隔离级别再按业务需要调整驱动只负责把 SQL 发过去。6. 运行中读写Connection.autocommit属性❌conn.autocommit True之后就假设切换立即生效 —— 这是可选扩展且写属性已被 PEP 249 标为弃用。✅ 在建立连接时通过构造参数确定模式或用驱动提供的方法不要靠改属性。7. 用同步 DB-API 的思维写异步驱动❌ 在 asyncmy / aiomysql 里写conn.cursor().execute(sql)就直接取值 —— 拿到的是协程对象不是结果。✅ 连接、游标、执行、取结果一律await连接的获取与释放用async with管。总结环节关键结论驱动Python 不内置 MySQL 驱动同步驱动都遵循 DB-API 2.0异步驱动不在其内契约apilevel/threadsafety/paramstyle是模块级常量paramstyle决定占位符写法迁移核心 API 名字不变连接参数、占位符、私有异常码必须逐个核对事务规范要求自动提交初始关闭未提交就close()会隐式回滚隔离级别属数据库层结果集executemany返回值未定义大结果集用arraysizefetchmany()或驱动级流式游标生产连接池复用、显式超时、探活、最小权限、凭据外置、utf8mb4对齐MySQL 这条线的复杂度几乎都不在 API 名字上而在驱动之间的细微契约差异、事务与隔离级别的语义、连接的复用与生命周期这三处。记牢 PEP 249 的公共契约再对差异保持警惕选型和迁移就都不会乱。

相关新闻

DataGrip 驱动管理实战:Oracle、MySQL、MongoDB 连接配置与避坑指南

DataGrip 驱动管理实战:Oracle、MySQL、MongoDB 连接配置与避坑指南

简介:这份资源是面向使用 JetBrains DataGrip 进行多数据库开发的工程师整理的离线驱动包集合,重点解决 Oracle、MySQL、MongoDB、PostgreSQL、SQL Server 等数据库在无外网或驱动下载受限环境下无法正常连接的问题。包内共 121 个文件,以 27…

2026/10/11 10:17:07 阅读更多 →
AIDI深度学习模型接入C#上位机:从P/Invoke到缺陷检测全流程

AIDI深度学习模型接入C#上位机:从P/Invoke到缺陷检测全流程

简介:这是一份面向C#开发者的AIDI深度学习框架调用示例包,用于在.NET项目中完成AIDI集成、模型加载与推理调用,可应用到图像识别、自然语言处理等深度学习场景。压缩包共34个文件,约1.42MB,主要包含C#源码(…

2026/10/11 10:17:07 阅读更多 →
pstack 实战指南:用调用栈快速定位线上死锁与 CPU 飙高

pstack 实战指南:用调用栈快速定位线上死锁与 CPU 飙高

凌晨两点,线上一个服务进程 CPU 飙到 99%,客户端超时告警一片,可你连它在哪个函数里忙都看不到。这种时候,我最先掏出来的工具就是 pstack。pstack 是一条命令行工具,作用只有一个:打印某个运行中进程的所有…

2026/10/11 10:17:07 阅读更多 →

最新新闻

Linux C++符号混淆实战:从符号泄露到崩溃还原

Linux C++符号混淆实战:从符号泄露到崩溃还原

上个月处理一个发布版Linux软件被逆向的排查,第一次动手就发现一个很扎心的现象:那个C项目没做任何符号层面的处理,对手一条nm命令下来,整个项目的内部函数名、类名、全局变量全部原样躺在那里。软件里有一块自研的核心算法&#…

2026/10/11 13:08:48 阅读更多 →
MFC下载器开发实战:WinInet、进度条与自绘界面

MFC下载器开发实战:WinInet、进度条与自绘界面

简介:这是一份MFC单文档/对话框框架下的文件下载工程源码包,面向Win32桌面应用初学者与需要实现HTTP下载、进度反馈和自定义界面的C开发者。包内包含完整的工程文件、界面位图资源、说明文档及编译生成文件,涵盖CInternetSession/CHttpFile的…

2026/10/11 13:08:48 阅读更多 →
VS2019 MFC双人五子棋实战:编译环境配置与核心代码解析

VS2019 MFC双人五子棋实战:编译环境配置与核心代码解析

简介:基于MFC框架的双人五子棋完整工程,已配好VS2019编译环境,适合有一定C基础、正在学习Windows界面编程或博弈算法实现的开发者。程序使用纯图形界面,支持黑白双方轮流落子、自动判断胜负、悔棋,以及棋局的保存与打开…

2026/10/11 13:08:48 阅读更多 →
BWO-KELM预测:白鲸优化调参提升KELM泛化能力

BWO-KELM预测:白鲸优化调参提升KELM泛化能力

简介:本资源是一套基于MATLAB实现的智能优化算法与机器学习融合的回归预测方案,面向高校研究生、科研人员及工程技术人员,解决小样本非线性回归建模中模型参数调优难、泛化能力弱等实际问题。压缩包共6个文件(4个核心m脚本、1个加…

2026/10/11 13:08:48 阅读更多 →
商品评论情感分析毕业设计:Python数据清洗到GUI模型部署全流程

商品评论情感分析毕业设计:Python数据清洗到GUI模型部署全流程

简介:一套基于Python的机器学习商品评论情感分析毕业设计完整项目,采用SVM与LSTM算法,并提供GUI可视化界面,适合计算机相关专业学生完成大作业、毕业设计及项目实战练习。项目经导师指导并评审通过,评分98分&#xff0…

2026/10/11 13:08:48 阅读更多 →
ImageJ Windows版从闪退到批量出图:内存设置、宏批处理与插件安装全攻略

ImageJ Windows版从闪退到批量出图:内存设置、宏批处理与插件安装全攻略

简介:这款ImageJ Windows版本采用64位Java 8捆绑,开箱即用,适合生物医学、材料科学等领域研究人员进行图像分析与测量。资源共430个文件,压缩包约47.72MB,以ijm宏、dll动态库、jar插件和java源码为主,同时内…

2026/10/11 13:07:48 阅读更多 →

日新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/11 0:00:27 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/11 0:00:27 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 10:45:37 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 21:32:20 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 10:38:42 阅读更多 →