1. 程式人生 > >python之Django的入門08------事務管理、悲觀鎖、樂觀鎖

python之Django的入門08------事務管理、悲觀鎖、樂觀鎖

我們接著上一篇文章的基礎上,來繼續瞭解進一步的Django框架

一.事務管理

在實際專案裡,事務管理是一個很重要的內容。 他可以保證一系列類操作要不全部成功要不全部失敗。也可以保證當多個應用程式在併發訪問資料庫時,可以在這些應用程式之間提供一個隔離方法,以防止彼此的操作互相干擾。

特性:

		 原子性:一組操作,要麼成功,要麼撤回
         穩定性:有非法資料,事務撤回,比如外來鍵連線
         隔離性:事務是獨立執行的,一個事務的處理結果,影響了其他事務,其他事務會撤回
         可靠性:當出現軟體或者硬體崩潰的情況,資料表會驅動日誌檔案進行重構修改

事務管理語句:

    1.開啟一個事務管理
    begin
    2.提交操作,對於資料庫的操作是永久性的
    commit     /    commit work
    3.回滾會撤銷所有未被提交的操作
    rollback   /   rollback work

事務的隔離級別:

	1.讀取未被提交的內容(髒讀)   read uncommitted
    2.讀取提交的內容(資料庫預設的隔離級別)  read committed
    3.可重複讀(易引起幻讀)
    4.可序列:最高級別,強制事務排序(本質是在每一個讀的資料行上加共享鎖,可能會帶來大量的超時現象和鎖競爭)

二、樂觀鎖
總是認為不會產生併發問題,每次去取資料的時候總認為不會有其他執行緒對資料進行修改,因此不會上鎖,但是在更新時會判斷其他執行緒在這之前有沒有對資料進行修改

三、悲觀鎖
總是假設最壞的情況,每次取資料時都認為其他執行緒會修改,所以都會加鎖(讀鎖、寫鎖、行鎖等),當其他執行緒想要訪問資料時,都需要阻塞掛起。可以依靠資料庫實現,如行鎖、讀鎖和寫鎖等,都是在操作之前加鎖

四、例子

from django.db import transaction

                '''悲觀鎖下訂單(存在事務管理)'''
                class TradeCommitView(View):

                    @transaction.atomic   #裝飾器的方法實現事務管理
                    def post(self,request):
                        '''設定儲存點用於事務管理'''
                        sid1 = transaction.savepoint()

                        user = request.user
                        if not user.is_authenticated():
                            '''判斷是否登陸'''
                            return redirect(reverse('car:index'))
                        # 接收資料
                        car_id = request.POST.get('car_id')
                        pay_method = request.POST.get('pay_style')
                        address_id = request.POST.get('address')
                        from datetime import datetime
                        order_id = str(user.id) + datetime.now().strftime('%Y%m%d%H%M%S')
                        # 運費(元)
                        transport = 5000
                        if not all([car_id,pay_method,address_id]):
                            return JsonResponse({'errmsg':'資料內容不完整'})
                        
                        try:
                            # car = CarDetail.objects.get(id=car_id)

                            #悲觀鎖
                            car = CarDetail.objects.select_for_update().get(id=car_id)
                        except:
                            transaction.savepoint_rollback(sid1)
                            return HttpResponse('車輛不存在')

                        service = float(car.car_price) * 10000 * 0.04
                        if service < 3000:
                            service = 3000
                       
                        add = AddressInfo.objects.get(id=address_id)

                        # sid1 = transaction.savepoint()

                        #建立訂單
                        try:
                            order_new = OrderInfo.objects.create(
                                order_id = order_id,
                                user = user,
                                add = add,
                                price = car.car_price,
                                service_charge =service,
                                freight =transport,
                                # status = 0,
                                # pay_method =
                                online_pai_method = pay_method
                            )
                            import time
                            # time.sleep(30)
                            if car.status != 1:   #如果車輛不是上線狀態
                                transaction.savepoint_rollback(sid1)   #回退到儲存點
                                return JsonResponse({'errmsg':'下單失敗'})
                            order_car =OrderCar.objects.create(
                                oder=order_new,
                                car_id = car,
                                comment='')
                            car.status = 0
                            car.save()

                        except Exception as e:
                            transaction.savepoint_rollback(sid1)
                            return JsonResponse({'errmsg':e})


                        transaction.savepoint_commit(sid1)
                        return HttpResponse('結束')

'''樂觀鎖下訂單(存在事務管理)'''
        class TradeCommitView_le(View):

            @transaction.atomic
            def post(self, request):
                '''設定儲存點用於事務管理'''
                sid1 = transaction.savepoint()

                user = request.user
                if not user.is_authenticated():
                    '''判斷是否登陸'''
                    return redirect(reverse('car:index'))
                # 接收資料
                car_id = request.POST.get('car_id')
                pay_method = request.POST.get('pay_style')
                address_id = request.POST.get('address')
                from datetime import datetime
                order_id = str(user.id) + datetime.now().strftime('%Y%m%d%H%M%S')
                # 運費(元)
                transport = 5000
                if not all([car_id, pay_method, address_id]):
                    return HttpResponse('資料內容不完整')
                # 校驗資料的正確(作業)
                try:
                    car = CarDetail.objects.get(id=car_id)

                except:
                    pass

                service = float(car.car_price) * 10000 * 0.04
                if service < 3000:
                    service = 3000
              
                add = AddressInfo.objects.get(id=address_id)

                # sid1 = transaction.savepoint()

                # 建立訂單
                try:
                    order_new = OrderInfo.objects.create(
                        order_id=order_id,
                        user=user,
                        add=add,
                        price=car.car_price,
                        service_charge=service,
                        freight=transport,
                        # status = 0,
                        # pay_method =
                        online_pai_method=pay_method
                    )



                    #樂觀鎖。不是真正意思上的鎖,只是在更新前查詢,如果不符合條件就回滾,符合就繼續執行。
                    res = CarDetail.objects.filter(id=car_id,status=1).update(status=0)
                    print('res',res)
                    if res == 0 :
                        transaction.savepoint_rollback(sid1)
                        return HttpResponse('車輛不存在')



                    order_car = OrderCar.objects.create(
                        oder=order_new,
                        car_id=car,
                        comment='')


                except Exception as e:
                    transaction.savepoint_rollback(sid1)
                    return JsonResponse({'errmsg': e})

                transaction.savepoint_commit(sid1)

                return render(request,'trade_pay.html',context={'order_id':order_id})