当前位置: 首页 > news >正文

Python 如何使用 MySQL 的事务

后端开发中,转账、订单创建、库存扣减这类业务,必须保证多条数据库操作全部成功或者全部回滚,这就是事务的价值。本文基于 pymysql 讲解 Python 下 MySQL 事务完整用法,包含原理、代码示例、异常处理、常见坑与最佳实践。

环境准备

安装 pymysql

pipinstallpymysql

注意:MySQL 只有 InnoDB 引擎支持事务,MyISAM 不支持事务。

测试表准备

CREATETABLE`account`(`id`INTPRIMARYKEYAUTO_INCREMENT,`username`VARCHAR(32)NOTNULL,`balance`DECIMAL(12,2)NOTNULLDEFAULT0)ENGINE=InnoDBDEFAULTCHARSET=utf8mb4;INSERTINTOaccount(username,balance)VALUES('zhangsan',1000.00),('lisi',1000.00);

什么是事务

事务是一组SQL操作的逻辑单元:

  • 全部执行成功,执行commit()提交,修改永久生效;
  • 任意步骤失败,执行rollback()回滚,撤销这一组所有修改。

ACID四大特性

  • 原子性(Atomicity):事务内操作不可分割,全部成功或全部失败。
  • 一致性(Consistency):事务执行前后业务数据保持合法状态。
  • 隔离性(Isolation):多个事务之间互相隔离,受事务隔离级别控制。
  • 持久性(Durability):commit提交之后,修改永久保存,数据库宕机也不会丢失。

pymysql事务核心要点

  1. pymysql 默认autocommit=True,每条SQL执行后立即提交,此时没有事务效果
  2. 使用事务必须关闭自动提交:conn.autocommit(False)
  3. 两个关键方法:
    • conn.commit():提交事务
    • conn.rollback():回滚事务
  4. 同一个事务必须使用同一个connection连接对象,不能换连接。

示例1:转账业务(try‑except标准写法)

张三转账200元给李四,模拟业务异常回滚。

importpymysqldeftransfer():conn=pymysql.connect(host="127.0.0.1",port=3306,user="root",password="xxx",database="test_db",charset="utf8mb4")# 关闭自动提交,开启事务模式conn.autocommit(False)cursor=conn.cursor(pymysql.cursors.DictCursor)try:# 1. 张三扣200cursor.execute("UPDATE account SET balance = balance - %s WHERE username = %s",(200,"zhangsan"))# 2. 模拟异常,触发回滚# 1 / 0# 3. 李四加200cursor.execute("UPDATE account SET balance = balance + %s WHERE username = %s",(200,"lisi"))# 全部成功,提交事务conn.commit()print("事务提交成功")exceptExceptionase:# 出现任何异常,回滚所有变更conn.rollback()print(f"事务回滚,异常:{e}")finally:cursor.close()conn.close()if__name__=="__main__":transfer()

打开代码中1/0模拟报错,你会发现两条update全部失效,不会出现张三扣钱、李四没加钱的数据错乱。

示例2:with上下文管理器用法

pymysql 的 connection 支持 with,退出上下文如果没有commit会自动回滚。

importpymysqldeftransfer_with():conn=pymysql.connect(host="127.0.0.1",user="root",password="xxx",database="test_db",autocommit=False,charset="utf8mb4")try:withconn.cursor(pymysql.cursors.DictCursor)ascur:cur.execute("UPDATE account SET balance=balance-%s WHERE username=%s",(100,"zhangsan"))cur.execute("UPDATE account SET balance=balance+%s WHERE username=%s",(100,"lisi"))# with游标结束不会自动commit,需要手动提交conn.commit()print("提交成功")exceptExceptionase:conn.rollback()print(f"回滚:{e}")finally:conn.close()

⚠️重要提醒:with cursor()只是管理游标,不会自动commit/rollback,事务的提交回滚仍然由connection控制。

示例3:嵌套事务?MySQL没有真正嵌套事务

MySQL InnoDB 不支持真正嵌套事务,可以使用保存点 savepoint实现局部回滚。

defsavepoint_demo():conn=pymysql.connect(host="127.0.0.1",user="root",password="xxx",database="test_db",autocommit=False)cur=conn.cursor()try:cur.execute("UPDATE account SET balance=balance-50 WHERE username='zhangsan'")# 设置保存点cur.execute("SAVEPOINT sp1")cur.execute("UPDATE account SET balance=balance+50 WHERE username='lisi'")# 回滚到保存点sp1,只撤销后面的操作,前面的保留cur.execute("ROLLBACK TO SAVEPOINT sp1")conn.commit()exceptExceptionase:conn.rollback()print(e)finally:cur.close()conn.close()

常见踩坑清单

  1. autocommit忘记关闭
    autocommit=True时每一条SQL直接生效,commit/rollback完全无效,事务失效。

  2. 事务中途更换connection对象
    同一个事务的多条SQL必须在同一个连接,换连接等于新开另一个事务。

  3. 查询不会加锁,update/delete才会产生事务变更
    普通select不会修改数据;SELECT ... FOR UPDATE会开启行锁,用于并发扣库存场景。

  4. 异常捕获后忘记rollback
    如果发生异常不执行rollback,未提交的事务会一直挂起,占用数据库锁资源,产生锁等待。

  5. MyISAM引擎使用事务
    MyISAM不支持事务,commit/rollback调用无效果,建表必须指定ENGINE=InnoDB

  6. 长事务
    事务不要长时间不commit/rollback,长事务会大量占用回滚段、锁资源,严重影响数据库性能。

结合SELECT FOR UPDATE(并发扣库存场景)

悲观锁示例,防止并发超卖

defdeduct_stock():conn=pymysql.connect(host="127.0.0.1",user="root",password="xxx",database="test_db",autocommit=False)cur=conn.cursor()try:# for update 行锁,其他事务会阻塞此处cur.execute("SELECT balance FROM account WHERE username='zhangsan' FOR UPDATE")row=cur.fetchone()ifrow[0]>=100:cur.execute("UPDATE account SET balance=balance-100 WHERE username='zhangsan'")conn.commit()exceptExceptionase:conn.rollback()print(e)finally:cur.close()conn.close()

最佳实践总结

  1. 业务涉及多写操作,必须使用事务;设置autocommit=False
  2. 使用try‑except‑finally,异常分支必须执行rollback(),最后关闭连接。
  3. 事务粒度尽量小,避免长事务,执行完尽快commit或rollback释放锁。
  4. 并发场景需要锁时,合理使用SELECT ... FOR UPDATE悲观锁,或业务层乐观锁。
  5. 确认表引擎为InnoDB。
  6. 一个事务全程复用同一个数据库连接对象。

如果你使用 SQLAlchemy ORM,框架会封装事务逻辑,但底层依然是MySQL事务机制。

http://www.jsqmd.com/news/1361403/

相关文章:

  • .NET异步监控的3个关键预警机制与实战方案
  • 别再把权限写进提示词:Agent 外部控制面的可运行设计
  • 2026年跨境电商出海必看:AI搜索生成式引擎(GEO)优化服务商大盘点,附合作避坑指南与适配选型攻略 - 商业大观
  • LunaTranslator:3步解决视觉小说语言障碍,让日文游戏无障碍畅玩
  • 资源型与技术型项目获取的核心差异与实战策略
  • 大模型应用系列:从Ranking到Reranking
  • 免费开源的键盘节奏游戏终极指南:Etterna完全体验
  • 探秘河南省建设劳动学会网站深度解析如何成为行业同仁的智慧宝库
  • 十分钟实现网页交互式几何画板:SVG+Two.js+响应式模型实战
  • 施工安全设施检测数据集 | 10600张YOLO智慧工地数据集
  • 2026年电商行业AI搜索优化服务商甄选指南:多维度盘点+合作避坑全维度FAQ - U渠道
  • 2026年找无人机缩管供应商哪家强?认准宁波易弯机械科技有限公司 - 热点品牌推荐
  • LLM应用反馈闭环工程:从Bad Case收集到模型迭代的完整实践
  • Python能不能写一个验证事务效果的样例代码
  • SpringBoot构建智能岗位推荐系统设计与实现
  • 在线开发平台集成LLM模型管理:统一抽象层、多模型策略与成本管控实践
  • 3个关键优势让平衡车电机控制性能提升300%:FOC场定向控制技术深度解析
  • Servlet核心技术解析与Java Web开发实践
  • BiliDownloader技术深度解析:构建高效B站视频下载架构的现代.NET实践
  • 一文读懂AMD Whisper Small ONNX-NPU:核心功能、优势及应用场景解析
  • 初探Ranking系统的离在线满意度评估
  • RF-DETR:基于Transformer的实时目标检测与实例分割模型深度解析与实践指南
  • SpringBoot运动健康管理系统开发实战与优化
  • 2026年本地零售行业全域流量优化服务商大盘点 合规实力选型攻略+签约避坑全维度FAQ - 产业观察报
  • Windows下Claude智能体优雅处理Ctrl+C:进程管理与信号处理实战
  • 2026绍兴装修避坑5条:无论选哪家装修公司,这几点必须做到 - 装修新知园
  • AI Agent调试黑匣子:实现LLM调用确定性回放与状态快照
  • ScrollableLayout进阶技巧:自定义OverScrollListener实现独特交互
  • DeepSeek-V4-Pro-Qwen3.5-4B-8bit震撼发布:MLX社区首款8bit量化多模态模型深度解析
  • 2026年名企求职机构推荐机构选择指南:避坑与高效上岸全解析 - 品牌报告