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

Python能不能写一个验证事务效果的样例代码

很多开发者学习MySQL事务的时候只停留在理论层面,不知道事务真正生效是什么样子。本文提供两套对照可运行代码:无事务产生脏数据、开启事务异常自动回滚。直接运行代码,观察数据库数据变化,直观验证事务效果。

环境准备

安装依赖

pipinstallpymysql

测试表SQL

必须使用InnoDB引擎,MyISAM不支持事务。

CREATETABLE`account`(`id`INTPRIMARYKEYAUTO_INCREMENT,`username`VARCHAR(32)NOTNULL,`balance`DECIMAL(12,2)NOTNULLDEFAULT0)ENGINE=InnoDBDEFAULTCHARSET=utf8mb4;-- 初始化测试数据:张三、李四各1000元INSERTINTOaccount(username,balance)VALUES('张三',1000.00),('李四',1000.00);

业务场景:张三转账200元给李四。
流程:

  1. 张三余额扣减200
  2. 模拟程序抛出异常
  3. 李四余额增加200

案例一:不使用事务(自动提交,产生脏数据)

pymysql默认autocommit=True,每执行一条SQL就直接写入数据库。
当中间代码抛出异常,后面SQL无法执行,就会出现一部分成功、一部分失败的数据错乱。

importpymysqldefdemo_without_transaction():# 默认 autocommit=Trueconn=pymysql.connect(host="127.0.0.1",port=3306,user="root",password="你的密码",database="test_db",charset="utf8mb4")cursor=conn.cursor()# 1.张三扣200,这条SQL立刻生效落库cursor.execute("UPDATE account SET balance = balance - %s WHERE username=%s",(200,"张三"))# 模拟业务异常、接口报错、程序崩溃print("模拟程序发生异常")1/0# 2.李四加钱,这行代码永远不会执行cursor.execute("UPDATE account SET balance = balance + %s WHERE username=%s",(200,"李四"))cursor.close()conn.close()if__name__=="__main__":demo_without_transaction()

运行现象

  1. 程序抛出ZeroDivisionError异常终止
  2. 查询数据库:张三余额变成800,李四仍然1000
  3. 出现脏数据,钱凭空消失,业务逻辑被破坏

⚠️复现完成后记得重置表数据,方便测试下一个案例。

UPDATEaccountSETbalance=1000.00;

案例二:开启事务,异常自动回滚

关键点:

  1. 设置conn.autocommit = False关闭自动提交
  2. 所有修改操作先在事务缓冲区,不会真正写入数据库
  3. 正常执行完毕调用conn.commit()持久化数据
  4. 捕获异常调用conn.rollback()撤销全部修改
importpymysqldefdemo_with_transaction():conn=pymysql.connect(host="127.0.0.1",port=3306,user="root",password="你的密码",database="test_db",charset="utf8mb4")# 关闭自动提交,开启事务模式conn.autocommit=Falsecursor=conn.cursor()try:# 第一步:张三扣款cursor.execute("UPDATE account SET balance = balance - %s WHERE username=%s",(200,"张三"))# 模拟异常,触发回滚逻辑print("模拟程序发生异常")1/0# 第二步:李四收款cursor.execute("UPDATE account SET balance = balance + %s WHERE username=%s",(200,"李四"))# 全部执行成功,提交事务,数据真正写入数据库conn.commit()print("✅事务提交成功,转账完成")exceptExceptionase:# 出现任何异常,回滚本次事务所有变更conn.rollback()print(f"❌捕获异常,事务已全部回滚,异常信息:{e}")finally:cursor.close()conn.close()if__name__=="__main__":demo_with_transaction()

运行现象(异常分支)

  1. 程序抛出除零异常,进入except代码块执行rollback()
  2. 查询数据库,张三、李四余额依旧都是1000,数据完全没有变化
  3. 所有update操作全部撤销,不会产生脏数据

测试正常提交场景

把代码中的1 / 0注释掉,再次运行。

  • 不会触发异常,执行commit()
  • 数据库:张三800,李四1200,转账业务正常完成。

案例三:演示部分回滚(SAVEPOINT保存点)

MySQL支持保存点,可以实现事务内部局部回滚,不需要全部回滚。

importpymysqldefdemo_savepoint():conn=pymysql.connect(host="127.0.0.1",port=3306,user="root",password="你的密码",database="test_db",autocommit=False,charset="utf8mb4")cur=conn.cursor()try:cur.execute("UPDATE account SET balance=balance-100 WHERE username='张三'")# 设置保存点sp1cur.execute("SAVEPOINT sp1")cur.execute("UPDATE account SET balance=balance+100 WHERE username='李四'")# 回滚到保存点,撤销上面李四加钱操作,张三扣钱保留cur.execute("ROLLBACK TO SAVEPOINT sp1")conn.commit()print("保存点演示完成")exceptExceptionase:conn.rollback()print(f"异常回滚{e}")finally:cur.close()conn.close()

对比总结表

场景无事务 autocommit=True开启事务 autocommit=False
程序中途报错部分SQL生效,生成脏数据全部操作回滚,数据不变
程序正常结束逐条SQL立即生效commit之后统一生效

开发避坑要点

  1. autocommit=False是开启事务的前提,忘记关闭自动提交,commit/rollback完全无效。
  2. 同一个事务内所有SQL必须使用同一个connection对象,更换连接代表全新事务。
  3. 异常分支必须手动执行rollback(),否则未提交事务会挂起,占用数据库锁资源。
  4. 表引擎必须是InnoDB,MyISAM不支持事务。
  5. 尽量缩小事务粒度,避免长事务,长事务会造成锁等待、数据库性能下降。
  6. SELECT查询语句不会修改数据,不会产生事务变更;SELECT ... FOR UPDATE会增加行锁。

业务模板

订单、库存、转账等多写业务直接套用这套模板:

conn.autocommit=Falsetry:# 多条写sqlconn.commit()exceptException:conn.rollback()finally:conn.close()

通过以上样例代码,就可以直观验证MySQL事务原子性效果:一组操作要么全部成功,要么全部撤销。

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

相关文章:

  • 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年名企求职机构推荐机构选择指南:避坑与高效上岸全解析 - 品牌报告
  • 光模块技术解析:从原理到应用实践
  • LangChain与通义千问集成实战:从零构建AI智能体应用
  • Cosmic IDE:Android上的桌面级JVM开发环境完全指南
  • 实战案例:用hf_mirrors/OrderAndChaos/controlnet-inpaint-endpoint修复老照片的完整流程
  • 3ds Max 2022 安装激活全攻略:从版本选择到避坑指南
  • 2026年Java面试八股文核心考点与实战解析
  • Alertmanager 告警抑制(inhibit)与静默(Silence)生产实战指南
  • 2026本地生活服务全域流量优化服务商大全:合规性、性价比、落地性全维度解析+签约避坑指南 - 商业大观
  • 2026年如何筛选戴南优质的304无缝管优质厂商?认准江苏巨登不锈钢管业有限公司(戴南运营中心) - 热点品牌推荐
  • 大模型微调实战:LoRA参数配置与LLaMA Factory调优指南
  • 5分钟掌握Windows效率神器PowerToys:告别文件占用烦恼
  • OpenClaw本地AI智能体部署指南:从Docker安装到飞书接入实战
  • AI助手与Git工作流深度集成:自动化PR、智能调试与历史分析
  • 调用限制与用量边界:iOS 证书与描述文件检测 API 实践解析