Python 使用 MySQL 數(shù)據(jù)庫進行事務(wù)處理完整示例
一、事務(wù)核心概念(先理解再實操)
事務(wù)(Transaction)是數(shù)據(jù)庫操作的最小邏輯單元,遵循 ACID 原則:
- 原子性(Atomicity):要么全部執(zhí)行成功,要么全部失敗回滾
- 一致性(Consistency):執(zhí)行前后數(shù)據(jù)庫狀態(tài)保持一致
- 隔離性(Isolation):多個事務(wù)互不干擾
- 持久性(Durability):提交后數(shù)據(jù)永久保存
Python操作MySQL時,默認是自動提交(autocommit) 模式(執(zhí)行單條SQL會立即生效),而事務(wù)處理需要先關(guān)閉自動提交,手動控制提交/回滾。
二、完整事務(wù)處理代碼示例
以「轉(zhuǎn)賬場景」為例(經(jīng)典的事務(wù)應(yīng)用場景:A賬戶扣錢、B賬戶加錢,必須同時成功/失?。?/p>
import mysql.connector
from mysql.connector import Error
def transfer_money(from_id, to_id, amount):
"""
模擬轉(zhuǎn)賬的事務(wù)處理
:param from_id: 轉(zhuǎn)出賬戶ID
:param to_id: 轉(zhuǎn)入賬戶ID
:param amount: 轉(zhuǎn)賬金額
"""
connection = None
try:
# 1. 建立數(shù)據(jù)庫連接
connection = mysql.connector.connect(
host='localhost',
user='root',
password='123456',
database='test_db'
)
# 2. 關(guān)閉自動提交,開啟手動事務(wù)控制
connection.autocommit = False
cursor = connection.cursor()
# 3. 執(zhí)行事務(wù)內(nèi)的多個SQL操作
# 步驟1:扣除轉(zhuǎn)出賬戶金額
deduct_sql = "UPDATE account SET balance = balance - %s WHERE id = %s"
cursor.execute(deduct_sql, (amount, from_id))
# 步驟2:增加轉(zhuǎn)入賬戶金額
add_sql = "UPDATE account SET balance = balance + %s WHERE id = %s"
cursor.execute(add_sql, (amount, to_id))
# 模擬異常(可取消注釋測試回滾效果)
# raise Error("模擬轉(zhuǎn)賬異常,觸發(fā)回滾")
# 4. 所有操作執(zhí)行成功,提交事務(wù)
connection.commit()
print("轉(zhuǎn)賬成功!事務(wù)已提交")
except Error as e:
# 5. 發(fā)生異常,回滾事務(wù)(撤銷所有已執(zhí)行的SQL操作)
if connection:
connection.rollback()
print(f"轉(zhuǎn)賬失敗,事務(wù)已回滾!錯誤信息:{e}")
finally:
# 6. 釋放資源(關(guān)閉游標和連接)
if connection and connection.is_connected():
cursor.close()
# 恢復(fù)自動提交(可選,不影響,但規(guī)范)
connection.autocommit = True
connection.close()
print("數(shù)據(jù)庫連接已關(guān)閉")
# ==================== 測試前準備 ====================
# 先在MySQL中創(chuàng)建測試表和數(shù)據(jù):
# CREATE DATABASE IF NOT EXISTS test_db;
# USE test_db;
# CREATE TABLE IF NOT EXISTS account (
# id INT PRIMARY KEY,
# name VARCHAR(50),
# balance DECIMAL(10,2)
# );
# INSERT INTO account (id, name, balance) VALUES (1, '張三', 1000.00), (2, '李四', 500.00);
# ==================== 執(zhí)行轉(zhuǎn)賬測試 ====================
# 測試正常轉(zhuǎn)賬(張三給李四轉(zhuǎn)200元)
transfer_money(from_id=1, to_id=2, amount=200.00)三、關(guān)鍵操作解釋
- 關(guān)閉自動提交:
connection.autocommit = False是開啟事務(wù)的核心,關(guān)閉后執(zhí)行的SQL不會立即生效,需手動commit()。 - 事務(wù)提交:
connection.commit()僅當(dāng)所有SQL執(zhí)行無異常時調(diào)用,會將事務(wù)內(nèi)所有操作永久寫入數(shù)據(jù)庫。 - 事務(wù)回滾:
connection.rollback()僅在捕獲到異常時調(diào)用,會撤銷事務(wù)內(nèi)所有已執(zhí)行的SQL操作,恢復(fù)到事務(wù)開始前的狀態(tài)。 - 異常捕獲:
必須用try-except包裹所有事務(wù)內(nèi)的操作,確保任何錯誤都能觸發(fā)回滾,避免數(shù)據(jù)不一致。
四、拓展場景:批量操作事務(wù)
如果需要批量插入/更新多條數(shù)據(jù),事務(wù)同樣適用,示例如下:
def batch_insert_users(users):
"""批量插入用戶,使用事務(wù)保證全部成功/失敗"""
connection = None
try:
connection = mysql.connector.connect(
host='localhost',
user='root',
password='123456',
database='test_db'
)
connection.autocommit = False
cursor = connection.cursor()
insert_sql = "INSERT INTO user (name, age) VALUES (%s, %s)"
# 批量執(zhí)行SQL(效率更高)
cursor.executemany(insert_sql, users)
connection.commit()
print(f"批量插入 {cursor.rowcount} 條數(shù)據(jù)成功")
except Error as e:
if connection:
connection.rollback()
print(f"批量插入失敗,事務(wù)回滾:{e}")
finally:
if connection and connection.is_connected():
cursor.close()
connection.autocommit = True
connection.close()
# 測試批量插入
user_list = [("王五", 30), ("趙六", 28), ("孫七", 35)]
batch_insert_users(user_list)到此這篇關(guān)于Python 使用 MySQL 數(shù)據(jù)庫進行事務(wù)處理步驟的文章就介紹到這了,更多相關(guān)python mysql事務(wù) 內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
基于Python實現(xiàn)音樂節(jié)奏可視化效果
這篇文章主要為大家詳細介紹了如何基于Python語言實現(xiàn)音樂節(jié)奏可視化效果,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-06-06
python游戲?qū)崙?zhàn)項目之俄羅斯方塊的魅力
遲早一定會掛掉的俄羅斯方塊,為什么至今仍是世界游戲之王?它是怎么編寫的?本文將給大家詳細的介紹,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值2021-09-09
Python爬蟲headers處理及網(wǎng)絡(luò)超時問題解決方案
這篇文章主要介紹了Python爬蟲headers處理及網(wǎng)絡(luò)超時問題解決方案,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-06-06
Python采集熱搜數(shù)據(jù)實現(xiàn)詳解
這篇文章主要為大家介紹了Python采集熱搜數(shù)據(jù)實現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-05-05

