一、鎖
行級鎖
- 返回一個鎖住行,值到事物結束的查詢集。
- 所有匹配的行將被鎖住,直到事物結束,這就意味著可以通過鎖防止資料被其他事務修改。
- 一般情況下如果其他事務鎖定了相關行,那麼本查詢將被阻塞直到鎖被釋放。
例子:
# 鎖定相關行
obj = Book.objects.select_for_update().filter(name='魔道祖師')
# 對滿足條件的資料加上互斥鎖。
# 由於mysql在查詢時自動加的是共享鎖,所以我們可以手動加上互斥鎖。
# create、update、delete操作時,mysql自動加上行級互斥鎖。
共享鎖(s):一般不用加都是自加的。
select * from table_name where ... lock in share mode;
排它鎖(x):我在操作這條資料別人不可以做任何操作 。
select * from table_name where ... for update;
二、事務
事務的四大特性
原子性(Atomicity)
原子性是指事務包含的所有操作要麼全部成功,要麼全部失敗回滾,因此事務的操作如果成功就必須要完全應用到資料庫,如果操作失敗則不能對資料庫有任何影響。
一致性(Consistency)
一致性是指事務必須使資料庫從一個一致性狀態變換到另一個一致性狀態,也就是說一個事務執行之後都必須處於一致性狀態。
拿轉賬來說,假設使用者A和使用者B兩者的錢加起來一共是5000,那麼不管A和B之間如何轉賬,轉幾次帳,事務結束後兩個使用者的錢加起來應該還的是5000,這就是事務的一致性
隔離性(Isolation)
隔離性是當多個使用者併發訪問資料庫時,比如操作同一張表時,資料庫為每一個使用者開啟事務,不能被其他事務的操作所幹擾,多個併發事務之間要相互隔離。
即要達到這麼一種效果:對於任意兩個併發的事務T1和T2,在事務T1看來,T2要麼在T1開始之前就結束,要麼在T1結束之後才開始,這樣每個事務都感覺不到有其他事務在併發執行
永續性(Durability)
永續性是指一個事務一旦被提交了,那麼對資料庫中的資料的改變就是永久性的,即使是在資料庫系統遇到故障的情況下也不會丟失提交事務的操作。
全域性開啟
工作流程:常用的事務處理方式是將每個請求都包裹在一個事務中,當請求過來時,Django會在呼叫檢視方法前開啟一個事務。如果請求和處理都正確,就返回結果,Django就會提交該事務。否則Django會回滾該事務。
例子:對統一個http請求對應的所有sql都放在一個事務中執行(要麼所有都成功,要麼所有都失敗),是全域性性配置。
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'books',
'HOST': '127.0.0.1',
'PORT': 3306,
'USER': 'root',
'PASSWORD': '123',
'OPTIONS': {
# 配置開啟嚴格sql模式
"init_command": "SET sql_mode='STRICT_TRANS_TABLES'"
},
'ATOMIC_REQUESTS': True, # 全域性開啟事務,繫結的是http請求響應整個過程
'AUTOCOMMIT': False, # 全域性取消自動提交(慎用)
},
# 配置其他資料庫
'app01':{
'ENGINE': 'django.db.backends.oracle',
.....
}
}
在全域性配置下:如果要針對某一個檢視函式做不受事務的管控,可以使用non_atomic_requests裝飾器。
from django.shortcuts import render
from books import models
from django.db import transaction # 需要匯入
@transaction.non_atomic_requests
def index(request):
# 此程式碼不在事務內執行
obj = models.Books.objects.filter().values()
return render(request, 'index.html', {'obj': obj})
atomic區域性使用事務
方法一:給函式做裝飾器來使用
from django.shortcuts import render
from books import models
from django.db import transaction
@transaction.atomic
def index(request):
# 此程式碼在事務內執行
obj = models.Books.objects.filter().values()
return render(request, 'index.html', {'obj': obj})
方法二:設定事務的儲存點,作為上下文管理器來使用
from django.shortcuts import render
from books import models
from django.db import transaction
def index(request):
# 次程式碼不在事務內執行
obj = models.Books.objects.filter().values()
with transaction.atomic(): # 儲存點
# 此程式碼在事務中執行
models.Books.objects.filter(id=1)
return render(request, 'index.html', {'obj': obj})