Python Coding Academy
🐍 آموزش جامع Python — پست ۲۲۹
مدیریت امن خطاهای تراکنش در SQLite
در پست قبل تستکردن عملیات Database را یاد گرفتیم. حالا میخواهیم یکی از مهمترین اصول کار با دیتابیس را بررسی کنیم: اگر یکی از عملیات شکست خورد، تغییرات ناقص باقی نمانند.
برای این کار از تراکنش (Transaction) و rollback() استفاده میکنیم.
🔹 مشکل اجرای چند عملیات
فرض کنیم میخواهیم دو حساب بانکی را بهروزرسانی کنیم. اگر مبلغ از حساب اول کم شود اما افزایش موجودی حساب دوم با خطا مواجه شود، اطلاعات ناسازگار خواهد شد.
تراکنش کمک میکند عملیات مرتبط را بهصورت یک واحد مدیریت کنیم.
🔹 استفاده از with connection:
import sqlite3
connection = sqlite3.connect("bank.db")
connection.execute("""
CREATE TABLE IF NOT EXISTS accounts (
id INTEGER PRIMARY KEY,
balance INTEGER NOT NULL
)
""")
connection.execute(
"INSERT OR IGNORE INTO accounts (id, balance) VALUES (?, ?)",
(1, 1000)
)
connection.execute(
"INSERT OR IGNORE INTO accounts (id, balance) VALUES (?, ?)",
(2, 500)
)
connection.commit()
try:
with connection:
connection.execute(
"UPDATE accounts SET balance = balance - ? WHERE id = ?",
(100, 1)
)
connection.execute(
"UPDATE accounts SET balance = balance + ? WHERE id = ?",
(100, 2)
)
except sqlite3.Error as error:
print("Transaction failed:", error)
connection.close()
در این مثال، هر دو تغییر داخل یک تراکنش قرار میگیرند. اگر خطای مناسب رخ دهد، تراکنش بازگردانده میشود؛ در غیر این صورت تغییرات ثبت میشوند.
🔹 بررسی نتیجه
بعد از تراکنش میتوانیم موجودیها را بخوانیم:
with sqlite3.connect("bank.db") as connection:
accounts = connection.execute("""
SELECT id, balance
FROM accounts
ORDER BY id
""").fetchall()
print(accounts)
اگر انتقال موفق باشد، موجودی حساب اول 900 و حساب دوم 600 خواهد بود.
🔹 چرا rollback() مهم است؟
فرض کنیم چند تغییر انجام شده، اما یکی از آنها شکست میخورد.
شروع تراکنش
↓
کاهش موجودی حساب اول
↓
خطا در عملیات بعدی
↓
rollback()
↓
لغو تغییرات تأییدنشده
به این ترتیب، تغییرات ناقص بهعنوان یک تراکنش موفق ثبت نمیشوند.
⚠️ نکته مهم
with connection: در صورت موفقیت تراکنش را تأیید میکند و در صورت خروج همراه با Exception، تغییرات تأییدنشده را بازمیگرداند.
این بلوک اتصال را نمیبندد؛ برای بستن اتصال باید جداگانه از close() یا مدیریت مناسب منابع استفاده کنیم.
خطاهایی که خودمان از نظر منطقی تشخیص نمیدهیم، لزوماً Exception ایجاد نمیکنند. مثلاً اگر UPDATE هیچ ردیفی را تغییر ندهد، باید تعداد ردیفهای تحت تأثیر را بررسی کنیم.
🧠 خلاصه
Transaction
↓
چند عملیات مرتبط
↓
موفقیت → commit
خطا → rollback
🎯 تمرین
برنامهای بنویس که در یک تراکنش:
از موجودی حساب اول 200 واحد کم کند.
به موجودی حساب دوم 200 واحد اضافه کند.
اگر هر عملیاتی خطا داد، تغییرات تراکنش را لغو کند.
در پایان موجودی هر دو حساب را چاپ کند.
پست ۲۲۹ از دوره جامع Python 🐍
2 ·