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)閉游標(biāo)和連接)
if connection and connection.is_connected():
cursor.close()
# 恢復(fù)自動提交(可選,不影響,但規(guī)范)
connection.autocommit = True
connection.close()
print("數(shù)據(jù)庫連接已關(guān)閉")
# ==================== 測試前準(zhǔ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)文章
C++/Python混合編程之小結(jié)Pybind11的使用
Pybind11是一個輕量級的C++庫,用于將你的C++代碼暴露給Python調(diào)用,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2025-05-05
學(xué)生如何注冊Pycharm專業(yè)版以及pycharm的安裝
這篇文章主要介紹了學(xué)生如何注冊Pycharm專業(yè)版以及pycharm的安裝,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09
學(xué)習(xí)python需要有編程基礎(chǔ)嗎
在本篇文章里小編給大家分享的是一篇關(guān)于學(xué)習(xí)python有哪些必要條件,需要的朋友們可以學(xué)習(xí)下。2020-06-06

