Python实现MySQL错误回滚机制的实战代码

 更新时间:2026年01月03日 09:22:10   作者:detayun  
这篇文章主要为大家详细介绍了如何通过Python和PyMySQL实现了一个包含异常回滚机制的转账场景,文中的示例代码讲解详细,感兴趣的小伙伴可以了解一下

前言

本文演示了一个数据库事务处理的典型案例:转账业务,可以通过Python和PyMySQL实现一个包含异常回滚机制的转账场景,当系统在扣款后、加款前发生故障时,能够自动回滚到事务开始前的状态,确保资金不会丢失

代码重点展示了事务控制的关键步骤:关闭自动提交、执行SQL操作、异常处理中的回滚机制,以及使用InnoDB引擎的必要性,通过模拟系统崩溃的场景,验证了事务的ACID特性,最终确保Alice和Bob的账户余额保持正确一致,

这个例子模拟了一个经典的“转账”场景:A 给 B 转钱,如果在扣款后、收款前系统发生错误(比如断电、代码异常),必须让数据回到转账前的状态,保证钱不凭空消失。

环境准备

你需要安装 pymysql 库:

pip install pymysql

代码实现

import pymysql
import sys

# 数据库配置(请根据你的实际情况修改)
DB_CONFIG = {
    'host': 'localhost',
    'user': 'root',
    'password': 'your_password',
    'database': 'test_db',
    'charset': 'utf8mb4'
}

def setup_database(cursor):
    """初始化测试表和数据"""
    try:
        cursor.execute("DROP TABLE IF EXISTS accounts")
        cursor.execute("""
            CREATE TABLE accounts (
                id INT AUTO_INCREMENT PRIMARY KEY,
                name VARCHAR(50),
                balance DECIMAL(10, 2)
            ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
        """)
        # 插入初始数据:Alice有1000元,Bob有500元
        cursor.execute("INSERT INTO accounts (name, balance) VALUES ('Alice', 1000.00)")
        cursor.execute("INSERT INTO accounts (name, balance) VALUES ('Bob', 500.00)")
        print("✅ 数据库初始化完成:Alice=1000, Bob=500")
    except Exception as e:
        print(f"❌ 初始化失败: {e}")

def transfer_money_with_rollback(from_user, to_user, amount):
    """
    模拟转账业务,并在发生错误时回滚
    """
    connection = None
    try:
        # 1. 建立连接
        connection = pymysql.connect(**DB_CONFIG)
        
        # 2. 关键步骤:关闭自动提交,开启事务
        connection.autocommit(False)
        
        with connection.cursor() as cursor:
            # --- 步骤一:扣款 ---
            print(f"\n💰 正在从 {from_user} 扣除 {amount} 元...")
            sql_deduct = "UPDATE accounts SET balance = balance - %s WHERE name = %s"
            cursor.execute(sql_deduct, (amount, from_user))
            
            # 模拟查询扣款后的余额(仅为了演示,实际业务中可能不需要)
            cursor.execute("SELECT balance FROM accounts WHERE name = %s", (from_user,))
            result = cursor.fetchone()
            print(f"   👉 扣款后查询 {from_user} 余额: {result[0]} (此时数据在内存/Redo Log中,未永久落盘)")

            # --- 步骤二:模拟突发异常 ---
            # 比如:此时服务器断电、网络中断、或者代码逻辑错误
            print("⚠️  模拟系统崩溃:准备加款时发生除零错误!")
            error_simulation = 1 / 0  # 故意制造一个异常
            
            # --- 步骤三:加款(正常情况下会执行,但上面报错了就不会走到这) ---
            sql_add = "UPDATE accounts SET balance = balance + %s WHERE name = %s"
            cursor.execute(sql_add, (amount, to_user))
            
            # 3. 如果一切顺利,提交事务
            connection.commit()
            print("✅ 转账成功,事务已提交!")

    except Exception as e:
        print(f"\n❌ 发生严重错误: {e}")
        if connection:
            # 4. 核心:发生任何异常,回滚所有操作
            print("🔄 正在执行回滚操作 (ROLLBACK)...")
            connection.rollback()
            print("🛡️ 回滚成功!数据已恢复到事务开始前的状态。")
            
    finally:
        if connection:
            # 5. 恢复自动提交模式并关闭连接
            connection.autocommit(True)
            connection.close()

def check_final_balance():
    """检查最终结果"""
    conn = pymysql.connect(**DB_CONFIG)
    with conn.cursor() as cursor:
        cursor.execute("SELECT name, balance FROM accounts")
        results = cursor.fetchall()
        print("\n----- 最终账户余额 -----")
        for row in results:
            print(f"用户: {row[0]}, 余额: {row[1]}")
        print("------------------------")
        # 验证结果
        alice_balance = results[0][1] if results[0][0] == 'Alice' else results[1][1]
        bob_balance = results[0][1] if results[0][0] == 'Bob' else results[1][1]
        assert alice_balance == 1000, f"Alice余额错误!期望1000,实际{alice_balance}"
        assert bob_balance == 500, f"Bob余额错误!期望500,实际{bob_balance}"
        print("🎉 验证通过:数据一致,回滚生效!")
    conn.close()

if __name__ == "__main__":
    # 初始化
    conn_init = pymysql.connect(**DB_CONFIG)
    with conn_init.cursor() as cur:
        setup_database(cur)
        conn_init.commit()
    conn_init.close()

    # 执行带回滚的转账
    transfer_money_with_rollback('Alice', 'Bob', 200)

    # 检查最终数据是否正确回滚
    check_final_balance()

代码讲解重点

  • connection.autocommit(False):这是事务的开关。默认情况下 MySQL 是自动提交的(每句 SQL 都是一个事务),关掉它才能把多步操作打包成一个整体。
  • try...except... 结构:业务逻辑必须放在 try 里。
  • connection.rollback():这是“后悔药”。一旦进入 except 块,调用此方法会撤销从 autocommit(False) 之后的所有未提交更改。
  • connection.commit():这是“确认键”。只有执行了这个,数据才真正写入磁盘(配合 Redo Log 和 Binlog)。
  • Engine=InnoDB:注意建表时指定了引擎为 InnoDB。如果是 MyISAM 引擎,它不支持事务,rollback 会失效!这是面试常考点。

运行这个脚本,你会看到虽然执行了扣款 SQL,但因为中间报错触发了回滚,最后 Alice 的钱还是 1000,Bob 还是 500,完美保证了数据的一致性。

到此这篇关于Python实现MySQL错误回滚机制的实战代码的文章就介绍到这了,更多相关Python MySQL错误回滚内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Python SQLAlchemy入门教程(基本用法)

    Python SQLAlchemy入门教程(基本用法)

    这篇文章主要介绍了Python SQLAlchemy入门教程,本文通过实例主要给大家讲解了python SQLAlchemy基本用法,需要的朋友可以参考下
    2019-11-11
  • Python 中的lambda函数介绍

    Python 中的lambda函数介绍

    Lambda函数,即Lambda 表达式(lambda expression),是一个匿名函数(不存在函数名的函数),这篇文章主要介绍了Python lambda函数的基础知识,需要的朋友可以参考下
    2018-10-10
  • Python中列表与元组的乘法操作示例

    Python中列表与元组的乘法操作示例

    这篇文章主要介绍了Python中列表与元组的乘法操作,结合简单实例形式分析了Python中列表、元组的乘法,并附带分析了字符串的乘法及元组乘法操作的注意事项,需要的朋友可以参考下
    2018-02-02
  • Python异常类型的使用及说明

    Python异常类型的使用及说明

    Python异常类型丰富且层次分明,涵盖运行时错误、设计意图异常、外部交互错误等,合理使用内置异常及自定义异常能提升代码健壮性与可维护性
    2025-07-07
  • python3+opencv3识别图片中的物体并截取的方法

    python3+opencv3识别图片中的物体并截取的方法

    今天小编就为大家分享一篇python3+opencv3识别图片中的物体并截取的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-12-12
  • 利用Python小工具实现3秒钟将视频转换为音频

    利用Python小工具实现3秒钟将视频转换为音频

    这篇文章主要介绍了利用Python小工具实现 3秒钟将视频转换为音频效果,本文给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-10-10
  • 让python的Cookie.py模块支持冒号做key的方法

    让python的Cookie.py模块支持冒号做key的方法

    虽然Cookie的标准是不允许:冒号出现在key里面的,但是我们的开发人员是很可爱的,常常会让我们意想不到。
    2010-12-12
  • Mysql分组查询group by与with rollup方式

    Mysql分组查询group by与with rollup方式

    这篇文章主要介绍了Mysql分组查询group by与with rollup方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-08-08
  • Python列表(list)所有元素的同一操作解析

    Python列表(list)所有元素的同一操作解析

    这篇文章主要介绍了Python列表(list)所有元素的同一操作解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-08-08
  • 使用Python开发智能文件备份工具

    使用Python开发智能文件备份工具

    在数字化时代,数据备份已成为个人和企业数据管理的重要环节,本文将详细介绍如何使用Python开发一款功能全面的桌面级文件备份工具,有需要的可以了解下
    2025-05-05

最新评论