python乐观锁和悲观锁
使用場景:
你銀行卡現在100塊,
A地花了10塊,然后A地停電,會有延遲扣款
然后你的公司給你同時發了200工資,
如果公司先査你的錢100,同時A地查也是查到100
你公司先update了,你現在300,
然后A地扣除,你現在就是90塊了.
這個地方樂觀鎖和悲觀鎖都可以選擇作為使用.
樂觀鎖就是A地要更新的時候先回去查一下有沒有被B地改了.
悲觀鎖就是A地讀取數據的時候,直接把銀行卡里的數據鎖死,禁止除了自己以外的人寫入.
那么,有沒有可能一句sql中,select后,update之前,被第三方人寫入截殺呢?
update salary_table set salary = salary + 1 where vesion = ***
cumt-pku-chiyu
這是不可能發生的,因為一句sql是保證完全事務的,復雜sql是自動開啟事務的,
事物具有原子性,如果不理解什么是事物,可以參考[3]
(上述案例來自微信網友r_R403)
?
一些實踐中的鎖的判斷方法(來自微信網友r_R403):
like %在前的是不走索引
主鍵也是索引
primary key和index都是走索引,導致行鎖
其余都是表鎖
不是全表掃描的都是行鎖
舉例(來自微信網友r_R403):
select ?math ?from zje where math>60 for update
表鎖,悲觀鎖
select ?math ?from zje where id>60 for update
行鎖,悲觀鎖
悲觀鎖就是sql里面帶有for update
?
如果是在django中,那么悲觀鎖的實現方式如下[1]:
obj = 模型類名.objects.select_for_update().get(id=1)
樂觀鎖實現案例[1]:
from django.shortcuts import render from django.http import JsonResponse from django.views.generic import View from django.db import transaction from 應用名.models import GoodsSKU# 類視圖 (并發,樂觀鎖) class MyView(View):@transaction.atomicdef post(self, request):'''訂單創建'''count = 3 # 訂購3件商品# 設置事務保存點s1 = transaction.savepoint()# 樂觀鎖,最多嘗試5次for i in range(5):# 查詢商品的信息(庫存)try:sku = GoodsSKU.objects.get(id=1)except:# 商品不存在transaction.savepoint_rollback(s1)return JsonResponse({'res': 1, 'errmsg': '商品不存在'})# 判斷商品的庫存if count > sku.stock:transaction.savepoint_rollback(s1)return JsonResponse({'res': 2, 'errmsg': '商品庫存不足'})# 更新商品的庫存和銷量orgin_stock = sku.stock # 原庫存 (數據庫隔離級別必須是Read Committed;如果是Repeatable Read,那么多次嘗試讀取的原庫存都是一樣的,讀不到其他線程提交更新后的數據。)new_stock = orgin_stock - count # 更新后的庫存new_sales = sku.sales + count # 更新后的銷量# update 商品表 set stock=new_stock, sales=new_sales where id=1 and stock = orgin_stock# 通過where子句中的條件判斷庫存是否進行了修改。(并發,樂觀鎖)# 返回受影響的行數res = GoodsSKU.objects.filter(id=1, stock=orgin_stock).update(stock=new_stock, sales=new_sales)if res == 0: # 如果修改失敗if i == 4:# 如果嘗試5次都失敗transaction.savepoint_rollback(s1)return JsonResponse({'res': 3, 'errmsg': '下單失敗'})continue # 再次嘗試# 否則更新成功# 跳出嘗試循環break# 提交事務transaction.savepoint_commit(s1)# 返回應答return JsonResponse({'res': 4, 'message': '創建成功'}適用場景[2]:
| 鎖 | 適用場景 |
| 悲觀鎖 | 寫入頻繁 |
| 樂觀鎖 | 讀取頻繁 |
注意,上述這個表格在實際應用中沒有標準細則,哪個能讓系統吞吐大就用哪個
Reference:
[1]Python Django,并發,悲觀鎖,select_for_update。樂觀鎖
[2]樂觀鎖和悲觀鎖的原理及應用場景
[3]mysql的事務操作
總結
以上是生活随笔為你收集整理的python乐观锁和悲观锁的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: jQuery的ajax里dataType
- 下一篇: clickhouse 行列转换