最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Python實現(xiàn)MySQL錯誤回滾機(jī)制的實戰(zhàn)代碼

 更新時間:2026年01月03日 09:22:10   作者:detayun  
這篇文章主要為大家詳細(xì)介紹了如何通過Python和PyMySQL實現(xiàn)了一個包含異?;貪L機(jī)制的轉(zhuǎn)賬場景,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下

前言

本文演示了一個數(shù)據(jù)庫事務(wù)處理的典型案例:轉(zhuǎn)賬業(yè)務(wù),可以通過Python和PyMySQL實現(xiàn)一個包含異常回滾機(jī)制的轉(zhuǎn)賬場景,當(dāng)系統(tǒng)在扣款后、加款前發(fā)生故障時,能夠自動回滾到事務(wù)開始前的狀態(tài),確保資金不會丟失

代碼重點展示了事務(wù)控制的關(guān)鍵步驟:關(guān)閉自動提交、執(zhí)行SQL操作、異常處理中的回滾機(jī)制,以及使用InnoDB引擎的必要性,通過模擬系統(tǒng)崩潰的場景,驗證了事務(wù)的ACID特性,最終確保Alice和Bob的賬戶余額保持正確一致,

這個例子模擬了一個經(jīng)典的“轉(zhuǎn)賬”場景:A 給 B 轉(zhuǎn)錢,如果在扣款后、收款前系統(tǒng)發(fā)生錯誤(比如斷電、代碼異常),必須讓數(shù)據(jù)回到轉(zhuǎn)賬前的狀態(tài),保證錢不憑空消失。

環(huán)境準(zhǔn)備

你需要安裝 pymysql 庫:

pip install pymysql

代碼實現(xiàn)

import pymysql
import sys

# 數(shù)據(jù)庫配置(請根據(jù)你的實際情況修改)
DB_CONFIG = {
    'host': 'localhost',
    'user': 'root',
    'password': 'your_password',
    'database': 'test_db',
    'charset': 'utf8mb4'
}

def setup_database(cursor):
    """初始化測試表和數(shù)據(jù)"""
    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
        """)
        # 插入初始數(shù)據(jù):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("? 數(shù)據(jù)庫初始化完成:Alice=1000, Bob=500")
    except Exception as e:
        print(f"? 初始化失敗: {e}")

def transfer_money_with_rollback(from_user, to_user, amount):
    """
    模擬轉(zhuǎn)賬業(yè)務(wù),并在發(fā)生錯誤時回滾
    """
    connection = None
    try:
        # 1. 建立連接
        connection = pymysql.connect(**DB_CONFIG)
        
        # 2. 關(guān)鍵步驟:關(guān)閉自動提交,開啟事務(wù)
        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))
            
            # 模擬查詢扣款后的余額(僅為了演示,實際業(yè)務(wù)中可能不需要)
            cursor.execute("SELECT balance FROM accounts WHERE name = %s", (from_user,))
            result = cursor.fetchone()
            print(f"   ?? 扣款后查詢 {from_user} 余額: {result[0]} (此時數(shù)據(jù)在內(nèi)存/Redo Log中,未永久落盤)")

            # --- 步驟二:模擬突發(fā)異常 ---
            # 比如:此時服務(wù)器斷電、網(wǎng)絡(luò)中斷、或者代碼邏輯錯誤
            print("??  模擬系統(tǒng)崩潰:準(zhǔn)備加款時發(fā)生除零錯誤!")
            error_simulation = 1 / 0  # 故意制造一個異常
            
            # --- 步驟三:加款(正常情況下會執(zhí)行,但上面報錯了就不會走到這) ---
            sql_add = "UPDATE accounts SET balance = balance + %s WHERE name = %s"
            cursor.execute(sql_add, (amount, to_user))
            
            # 3. 如果一切順利,提交事務(wù)
            connection.commit()
            print("? 轉(zhuǎn)賬成功,事務(wù)已提交!")

    except Exception as e:
        print(f"\n? 發(fā)生嚴(yán)重錯誤: {e}")
        if connection:
            # 4. 核心:發(fā)生任何異常,回滾所有操作
            print("?? 正在執(zhí)行回滾操作 (ROLLBACK)...")
            connection.rollback()
            print("??? 回滾成功!數(shù)據(jù)已恢復(fù)到事務(wù)開始前的狀態(tài)。")
            
    finally:
        if connection:
            # 5. 恢復(fù)自動提交模式并關(guān)閉連接
            connection.autocommit(True)
            connection.close()

def check_final_balance():
    """檢查最終結(jié)果"""
    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("------------------------")
        # 驗證結(jié)果
        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("?? 驗證通過:數(shù)據(jù)一致,回滾生效!")
    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()

    # 執(zhí)行帶回滾的轉(zhuǎn)賬
    transfer_money_with_rollback('Alice', 'Bob', 200)

    # 檢查最終數(shù)據(jù)是否正確回滾
    check_final_balance()

代碼講解重點

  • connection.autocommit(False):這是事務(wù)的開關(guān)。默認(rèn)情況下 MySQL 是自動提交的(每句 SQL 都是一個事務(wù)),關(guān)掉它才能把多步操作打包成一個整體。
  • try...except... 結(jié)構(gòu):業(yè)務(wù)邏輯必須放在 try 里。
  • connection.rollback():這是“后悔藥”。一旦進(jìn)入 except 塊,調(diào)用此方法會撤銷從 autocommit(False) 之后的所有未提交更改。
  • connection.commit():這是“確認(rèn)鍵”。只有執(zhí)行了這個,數(shù)據(jù)才真正寫入磁盤(配合 Redo Log 和 Binlog)。
  • Engine=InnoDB:注意建表時指定了引擎為 InnoDB。如果是 MyISAM 引擎,它不支持事務(wù),rollback 會失效!這是面試??键c。

運行這個腳本,你會看到雖然執(zhí)行了扣款 SQL,但因為中間報錯觸發(fā)了回滾,最后 Alice 的錢還是 1000,Bob 還是 500,完美保證了數(shù)據(jù)的一致性。

到此這篇關(guān)于Python實現(xiàn)MySQL錯誤回滾機(jī)制的實戰(zhàn)代碼的文章就介紹到這了,更多相關(guān)Python MySQL錯誤回滾內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論

德化县| 宜阳县| 旺苍县| 岳阳市| 柏乡县| 奇台县| 望奎县| 临沂市| 张家界市| 湟源县| 鄂尔多斯市| 寿阳县| 名山县| 临武县| 河北省| 平潭县| 津市市| 浮梁县| 洞头县| 海盐县| 登封市| 龙海市| 四平市| 江门市| 开封市| 洪泽县| 绍兴县| 屯留县| 库尔勒市| 衡水市| 清涧县| 枝江市| 东乡县| 含山县| 巩义市| 北京市| 喀喇| 石河子市| 丰顺县| 武川县| 上林县|