事务管理策略
- 原子性:确保表单提交涉及的多个数据库表写入操作要么全部成功,要么全部失败。在Django中,可以使用
transaction.atomic
装饰器或上下文管理器来实现。
- 一致性:保证数据库从一个一致状态转换到另一个一致状态。这意味着在事务执行前后,数据库的完整性约束(如唯一性约束、外键约束等)都必须得到满足。
- 隔离性:处理并发事务时,不同事务之间应相互隔离,避免相互干扰。Django使用数据库默认的隔离级别(通常是
READ COMMITTED
),在大多数情况下能满足需求。如果需要更严格的隔离,可以在数据库层面进行配置。
- 持久性:一旦事务提交成功,对数据库的修改应永久保存,即使系统出现故障也不会丢失。
锁机制的选择与使用
- 乐观锁:乐观锁假设在大多数情况下不会发生并发冲突,只有在提交事务时才检查是否有冲突。在Django中,可以通过版本控制字段实现乐观锁。例如,在模型中添加一个
version
字段,每次更新数据时递增该字段的值。在更新数据前,先获取当前的version
值,更新时检查version
值是否与获取的值相同,如果相同则更新成功,并递增version
值;否则说明有其他事务已修改数据,需要重新获取数据并进行更新。
- 悲观锁:悲观锁假设在并发情况下很可能发生冲突,因此在访问数据时就锁定数据,防止其他事务同时修改。在Django中,可以使用
select_for_update
方法实现悲观锁。例如,在获取数据时使用Model.objects.select_for_update().get(pk=1)
,这样在事务结束前,其他事务无法修改该数据。
代码实现
- 使用
transaction.atomic
装饰器:
from django.db import transaction
from.models import Model1, Model2
@transaction.atomic
def handle_form_submission(request):
if request.method == 'POST':
form = YourForm(request.POST)
if form.is_valid():
data1 = form.cleaned_data.get('data1')
data2 = form.cleaned_data.get('data2')
model1 = Model1.objects.create(field1=data1)
model2 = Model2.objects.create(field2=data2, related_model=model1)
return HttpResponse('Form submitted successfully')
else:
return HttpResponse('Form is invalid')
else:
form = YourForm()
return render(request, 'form_template.html', {'form': form})
- 使用
transaction.atomic
上下文管理器:
from django.db import transaction
from.models import Model1, Model2
def handle_form_submission(request):
if request.method == 'POST':
form = YourForm(request.POST)
if form.is_valid():
data1 = form.cleaned_data.get('data1')
data2 = form.cleaned_data.get('data2')
with transaction.atomic():
model1 = Model1.objects.create(field1=data1)
model2 = Model2.objects.create(field2=data2, related_model=model1)
return HttpResponse('Form submitted successfully')
else:
return HttpResponse('Form is invalid')
else:
form = YourForm()
return render(request, 'form_template.html', {'form': form})
- 乐观锁实现:
from django.db import transaction
from.models import ModelWithVersion
@transaction.atomic
def update_with_optimistic_lock(request):
if request.method == 'POST':
form = YourForm(request.POST)
if form.is_valid():
new_data = form.cleaned_data.get('new_data')
model = ModelWithVersion.objects.get(pk=1)
original_version = model.version
try:
model.field = new_data
model.version = original_version + 1
model.save(update_fields=['field','version'])
except DatabaseError:
# 处理版本冲突,重新获取数据并更新
model = ModelWithVersion.objects.get(pk=1)
model.field = new_data
model.version = model.version + 1
model.save(update_fields=['field','version'])
return HttpResponse('Data updated successfully')
else:
return HttpResponse('Form is invalid')
else:
form = YourForm()
return render(request, 'form_template.html', {'form': form})
- 悲观锁实现:
from django.db import transaction
from.models import ModelToLock
@transaction.atomic
def update_with_pessimistic_lock(request):
if request.method == 'POST':
form = YourForm(request.POST)
if form.is_valid():
new_data = form.cleaned_data.get('new_data')
with transaction.atomic():
model = ModelToLock.objects.select_for_update().get(pk=1)
model.field = new_data
model.save()
return HttpResponse('Data updated successfully')
else:
return HttpResponse('Form is invalid')
else:
form = YourForm()
return render(request, 'form_template.html', {'form': form})