Django之?dāng)?shù)據(jù)庫事務(wù)編程

原子.png

在了解 Django 數(shù)據(jù)庫事務(wù)編程前有必要先了解下數(shù)據(jù)庫事務(wù)。

數(shù)據(jù)庫事務(wù)(transaction)

數(shù)據(jù)庫事務(wù)是對數(shù)據(jù)的某一組修改(insert宽菜、update盼理、delete)操作要么全部執(zhí)行成功辅愿,要么全部執(zhí)行失敗智亮。

數(shù)據(jù)庫事務(wù)有如下特征:

  • 原子性(Atomicity):事務(wù)中的全部操作在數(shù)據(jù)庫中是不可分割的,要么全部完成点待,要么全部不執(zhí)行阔蛉。
  • 一致性(Consistency):幾個(gè)并行執(zhí)行的事務(wù),其執(zhí)行結(jié)果必須與按某一順序 串行執(zhí)行的結(jié)果相一致癞埠。
  • 隔離性(Isolation):事務(wù)的執(zhí)行不受其他事務(wù)的干擾状原,事務(wù)執(zhí)行的中間結(jié)果對其他事務(wù)必須是透明的。
  • 持久性(Durability):對于任意已提交事務(wù)燕差,系統(tǒng)必須保證該事務(wù)對數(shù)據(jù)庫的改變不被丟失遭笋,即使數(shù)據(jù)庫出現(xiàn)故障坝冕。

mysql 數(shù)據(jù)庫事務(wù)

以 mysql 為例徒探,其 Innodb 存儲(chǔ)引擎支持事務(wù)。

然后事務(wù)的 SQL 大概為:

begin

some sql ...

...

commit 

begin 的作用是開啟一個(gè)事務(wù)( 相當(dāng)于 SET AUTOCOMMIT=0 禁止自動(dòng)提交)喂窟,接下來可能執(zhí)行了幾個(gè) sql 語句测暗,但在 commit 前都還沒有在數(shù)據(jù)庫生效央串,直到 commit 成功后所有的修改才會(huì)生效。

事務(wù)使用注意事項(xiàng)

  • 如果沒有顯式的開啟事務(wù)碗啄,每條 SQL 語句都是一個(gè)事務(wù)
  • 一般的 select 無需開啟事務(wù)质和,除非是為了 update 執(zhí)行的 select
  • 使用事務(wù)必要涉及到鎖,要考慮鎖的影響

Django 數(shù)據(jù)庫事務(wù)

django 里主要使用 transaction (from django.db import transaction )來支持事務(wù)稚字,有以下兩種用法饲宿。

transaction.atomic 裝飾器

@transaction.atomic
def viewfunc(request):
    # This code executes inside a transaction.
    do_stuff()

給 viewfunc 增加 @transaction.atomic 使得此函數(shù)中所有的 insert、update胆描、delete 操作為一組事務(wù)瘫想。

with transaction.atomic

from django.db import transaction

def viewfunc(request):
    # This code executes in autocommit mode (Django's default).
    do_stuff()

    with transaction.atomic():
        # This code executes inside a transaction.
        do_more_stuff()

使用 with transaction.atomic 將事務(wù)操作覆蓋,由于此種方式比裝飾器方式能控制更小的范圍昌讲,最小化事務(wù)操作范圍国夜,推薦使用此種方式

Savepoints

Savepoints 用來設(shè)置一個(gè)保存點(diǎn)短绸,在其后的事務(wù)代碼中(即 transaction.atomic 覆蓋范圍內(nèi))车吹,可以將數(shù)據(jù)庫的修改 回滾(rollback)到保存點(diǎn)的那個(gè)位置。例如:

from django.db import transaction

# open a transaction
@transaction.atomic
def viewfunc(request):

    a.save()
    # transaction now contains a.save()

    sid = transaction.savepoint()

    b.save()
    # transaction now contains a.save() and b.save()

    if want_to_keep_b:
        transaction.savepoint_commit(sid)
        # open transaction still contains a.save() and b.save()
    else:
        transaction.savepoint_rollback(sid)
        # open transaction now contains only a.save()

transaction.atomic 使用注意事項(xiàng)

  1. 它只是數(shù)據(jù)庫層面的事務(wù)醋闭,不是python代碼級的事務(wù)窄驹,即它不能保證 python 代碼的并發(fā)性(例如對同一個(gè)全局變量修改)
  2. 對于只有查詢操作的函數(shù),不需要加 @transaction.atomic
  3. 對于只會(huì)執(zhí)行一條 SQL 語句的代碼或函數(shù)目尖,不需要加 transaction.atomic馒吴,因?yàn)橐粭l SQL 默認(rèn)就是一個(gè)事務(wù)。
  4. transaction.atomic 覆蓋的代碼中不要使用 try except 來捕獲 django.models 執(zhí)行的錯(cuò)誤瑟曲,否則會(huì)破壞事務(wù)的目的饮戳。
  5. transaction.atomic 覆蓋的代碼中不要包含耗時(shí)的操作,比如第三方系統(tǒng)給的網(wǎng)絡(luò)調(diào)用洞拨。因?yàn)槭聞?wù)會(huì)加鎖扯罐,如果網(wǎng)絡(luò)調(diào)用超時(shí),在 timeout 之前鎖不會(huì)釋放烦衣,可能會(huì)報(bào) (1213, 'Deadlock found when trying to get lock; try restarting transaction') 錯(cuò)誤
  6. 如果在事務(wù)中涉及對 select 后的結(jié)果進(jìn)行修改(例如對某個(gè)字段查詢后參與計(jì)算后再update回去)歹河,請使用 model.objects.select_for_update(),相當(dāng)于對此讀操作也加了鎖花吟。
  7. 如果 transaction.savepoint() 放在了事務(wù)函數(shù)的第一行秸歧,并且下面也沒有transaction.savepoint(),那么 savepoint 和 savepoint_rollback 都可以去掉衅澈,用默認(rèn)的方式即可键菱。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市今布,隨后出現(xiàn)的幾起案子经备,更是在濱河造成了極大的恐慌拭抬,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,542評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件侵蒙,死亡現(xiàn)場離奇詭異造虎,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)纷闺,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評論 3 394
  • 文/潘曉璐 我一進(jìn)店門算凿,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人犁功,你說我怎么就攤上這事澎媒。” “怎么了波桩?”我有些...
    開封第一講書人閱讀 163,912評論 0 354
  • 文/不壞的土叔 我叫張陵戒努,是天一觀的道長。 經(jīng)常有香客問我镐躲,道長储玫,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,449評論 1 293
  • 正文 為了忘掉前任萤皂,我火速辦了婚禮撒穷,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘裆熙。我一直安慰自己端礼,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,500評論 6 392
  • 文/花漫 我一把揭開白布入录。 她就那樣靜靜地躺著蛤奥,像睡著了一般。 火紅的嫁衣襯著肌膚如雪僚稿。 梳的紋絲不亂的頭發(fā)上凡桥,一...
    開封第一講書人閱讀 51,370評論 1 302
  • 那天,我揣著相機(jī)與錄音蚀同,去河邊找鬼缅刽。 笑死,一個(gè)胖子當(dāng)著我的面吹牛蠢络,可吹牛的內(nèi)容都是我干的衰猛。 我是一名探鬼主播,決...
    沈念sama閱讀 40,193評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼刹孔,長吁一口氣:“原來是場噩夢啊……” “哼啡省!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,074評論 0 276
  • 序言:老撾萬榮一對情侶失蹤冕杠,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后酸茴,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體分预,經(jīng)...
    沈念sama閱讀 45,505評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,722評論 3 335
  • 正文 我和宋清朗相戀三年薪捍,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了笼痹。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,841評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡酪穿,死狀恐怖凳干,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情被济,我是刑警寧澤救赐,帶...
    沈念sama閱讀 35,569評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站只磷,受9級特大地震影響经磅,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜钮追,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,168評論 3 328
  • 文/蒙蒙 一预厌、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧元媚,春花似錦轧叽、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,783評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至甥角,卻和暖如春腰埂,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背蜈膨。 一陣腳步聲響...
    開封第一講書人閱讀 32,918評論 1 269
  • 我被黑心中介騙來泰國打工屿笼, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人翁巍。 一個(gè)月前我還...
    沈念sama閱讀 47,962評論 2 370
  • 正文 我出身青樓驴一,卻偏偏與公主長得像,于是被迫代替她去往敵國和親灶壶。 傳聞我的和親對象是個(gè)殘疾皇子肝断,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,781評論 2 354