python / expert
Snippet
Django Transaktions Isolation Levels mit Savepoint Management
Dieses Snippet demonstriert erweiterte Django Transaktionsverwaltung mit Isolation Levels und Savepoint Handling. Der TransactionManager Context Manager bietet granulare Kontrolle über Transaktionsverhalten während der with_savepoint Decorator nested Transaction Support für recoverierbare Operationen ermöglicht. Der OrderProcessingService zeigt praktische Verwendung von select_for_update() für pessimistisches Locking, Savepoint Rollback für partielle Fehler und Atomic Blocks für gruppierte Operationen.
snippet.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
from django.db import transaction, connectionfrom django.db.transaction import Atomicfrom functools import wrapsimport logginglogger = logging.getLogger(__name__)class TransactionManager:def __init__(self, isolation_level=None):self.isolation_level = isolation_level or 'read committed'def __enter__(self):connection.set_autocommit(False)self.transaction = transaction.atomic()self.transaction.__enter__()return selfdef __exit__(self, exc_type, exc_val, exc_tb):if exc_type:self.transaction.__exit__(exc_type, exc_val, exc_tb)raise exc_valreturn self.transaction.__exit__(exc_type, exc_val, exc_tb)def with_savepoint(func):@wraps(func)def wrapper(*args, **kwargs):with transaction.savepoint():return func(*args, **kwargs)return wrapperclass OrderProcessingService:@with_savepointdef process_order(self, order_id, payment_data):from myapp.models import Order, Payment, Inventoryorder = Order.objects.select_for_update().get(id=order_id)with transaction.savepoint():inventory_check = Inventory.objects.select_for_update().filter(product_id=order.product_id,quantity__gte=order.quantity).exists()if not inventory_check:raise ValueError('Insufficient inventory')payment = Payment.objects.create(order=order,amount=order.total,**payment_data)with transaction.atomic(savepoint=True):Inventory.objects.filter(product_id=order.product_id).update(quantity=models.F('quantity') - order.quantity)order.status = 'processing'order.save()return orderdef bulk_process_with_recovery(self, order_ids):results = {'success': [], 'failed': []}for order_id in order_ids:try:with TransactionManager('repeatable read'):self.process_order(order_id, {})results['success'].append(order_id)except Exception as e:logger.error(f'Order {order_id} failed: {e}')results['failed'].append({'id': order_id, 'error': str(e)})return results
django
Erklärung
1
connection.set_autocommit(False)
Manuell Autocommit deaktivieren um Transaktionsgrenzen explizit im Context Manager zu kontrollieren
2
with transaction.savepoint()
Erstelle Savepoint innerhalb einer Transaktion für partielles Rollback ohne gesamte Transaktion abzubrechen
3
select_for_update()
Erwerbe pessimistisches Lock auf ausgewählte Rows verhindert gleichzeitige Modifikationen bis Transaktion committed
4
transaction.atomic(savepoint=True)
Erstelle Atomic Block der nested Savepoints für komplexe Operationen mit möglichen partiellen Fehlern unterstützt
5
isolation_level='repeatable read'
Setze Transaktions Isolation Level für konsistente Reads innerhalb derselben Transaktions-Session