目錄
- #概述
- #基本用法
- #事務一致性保障機制
- #破壞一致性的常見場景
- #高級用法
- #最佳實踐
- #診斷與調試
- #附錄
概述
transaction.atomic()
是 Django 提供的數據庫事務管理工具,用于確保一系列數據庫操作要么全部成功提交,要么全部回滾,維護數據的一致性。
基本用法
1. 作為上下文管理器
from django.db import transactiondef view_func(request):with transaction.atomic():# 事務內的操作obj1.save()obj2.save()
2. 作為裝飾器
@transaction.atomic
def view_func(request):# 整個函數都在事務中執行obj1.save()obj2.save()
事務一致性保障機制
- 進入塊時:創建保存點或開始新事務
- 成功退出:提交所有更改
- 異常退出:自動回滾所有更改
- 嵌套處理:內層塊作為保存點處理
破壞一致性的常見場景
1. 異常處理不當
with transaction.atomic():try:risky_operation()except Exception:logger.error("Error occurred") # 不重新拋出異常 → 破壞一致性
修復方案:
with transaction.atomic():try:risky_operation()except Exception as e:logger.error("Error occurred")raise # 重新拋出異常
2. 長時間運行事務
with transaction.atomic():process_data() # 耗時操作update_database() # 可能因鎖超時失敗
3. 混合非數據庫操作
with transaction.atomic():save_to_db()call_external_api() # 網絡操作save_to_db_again() # 外部API失敗可能導致不一致
4. 多數據庫操作
with transaction.atomic(): # 只針對default數據庫ModelA.objects.create(...) # defaultModelB.objects.using('other_db').create(...) # 不受保護
5. 隔離級別沖突
# 事務1
with transaction.atomic():item = Item.objects.select_for_update().get(pk=1)time.sleep(10)# 事務2 (并發執行)
with transaction.atomic():item = Item.objects.get(pk=1) # 可能被阻塞或讀取過期數據
高級用法
1. 手動保存點控制
with transaction.atomic():a.save()sid = transaction.savepoint() # 創建保存點try:b.save()except Exception:transaction.savepoint_rollback(sid) # 回滾到保存點# 可繼續其他操作transaction.savepoint_commit(sid) # 釋放保存點
2. 指定數據庫
with transaction.atomic(using='replica_db'):ReplicaModel.objects.create(...)
3. 嵌套事務控制
with transaction.atomic(): # 外層事務a.save()try:with transaction.atomic(): # 內層保存點b.save()raise ValueErrorexcept ValueError:pass # 僅回滾內層c.save() # 仍會提交
最佳實踐
- 保持事務簡短:只包含必要的數據庫操作
- 明確異常處理:
- 要么完全處理并確保一致性
- 要么重新拋出異常
- 避免混合操作:
- 不在事務中執行網絡/文件IO
- 不在事務中執行耗時計算
- 多數據庫處理:
with transaction.atomic(using='default'):with transaction.atomic(using='other_db'):# 跨數據庫操作
- 測試隔離級別:了解數據庫的默認隔離級別
- 監控長事務:設置數據庫長事務警報
診斷與調試
1. 檢查事務狀態
from django.db import connectionprint(f"In atomic block: {connection.in_atomic_block}")
print(f"Needs rollback: {connection.needs_rollback}")
2. 檢查隔離級別(PostgreSQL)
with connection.cursor() as cursor:cursor.execute("SHOW transaction_isolation")print(cursor.fetchone())
3. 日志記錄
LOGGING = {'loggers': {'django.db.backends': {'level': 'DEBUG','handlers': ['console'],}}
}
附錄
支持的數據庫后端
數據庫 | 支持級別 | 注意事項 |
---|---|---|
PostgreSQL | 完全支持 | 建議使用 |
MySQL/MariaDB | 支持 | 需使用InnoDB |
SQLite | 支持 | 實際是文件鎖 |
Oracle | 完全支持 | - |
SQL Server | 支持 | 需驗證隔離級別 |
事務隔離級別參考
級別 | 臟讀 | 不可重復讀 | 幻讀 | 說明 |
---|---|---|---|---|
讀未提交 | 可能 | 可能 | 可能 | 最低隔離 |
讀已提交 | 不可能 | 可能 | 可能 | 多數數據庫默認 |
可重復讀 | 不可能 | 不可能 | 可能 | MySQL默認 |
串行化 | 不可能 | 不可能 | 不可能 | 最高隔離 |