MySql 中的事務
事務什么是事務事務的特性(ACID)事務的分類扁平事務(Flat Transactions)鏈事務什么是鏈事務鏈事務與扁平事務的區別:嵌套事務什么是嵌套事務事務的隔離級別SQL標準定義的四個隔離級別:READ COMMITTED:提交讀REPEATABLE READ:可重復讀serializable:可串行讀Django 中的事務事務自動提交與手動提交:
事務
什么是事務
-
a 事務(Transaction)是數據庫區別于文件系統的重要特征之一,事務會把數據庫從一種一致性狀態轉換為另一種一致性狀態
-
b 在數據庫提交時,可以確保要么所有修改都已保存,要么所有修改都不保存
-
簡單來說就是干一系列事,要么最終完成,要么前面干的也都廢了
-
Mysql中關于事務的語句:
-
BEGIN或START TRANSACTION;顯式地開啟一個事務;
?
COMMIT;也可以使用COMMIT WORK,不過二者是等價的。COMMIT會提交事務,并使已對數據庫進行的所有修改稱為永久性的;
?
ROLLBACK;有可以使用ROLLBACK WORK,不過二者是等價的。回滾會結束用戶的事務,并撤銷正在進行的所有未提交的修改;
?
SAVEPOINT identifier;SAVEPOINT允許在事務中創建一個保存點,一個事務中可以有多個SAVEPOINT;
?
RELEASE SAVEPOINT identifier;刪除一個事務的保存點,當沒有指定的保存點時,執行該語句會拋出一個異常;
?
ROLLBACK TO identifier;把事務回滾到標記點;
?
SET TRANSACTION;用來設置事務的隔離級別。InnoDB存儲引擎提供事務的隔離級別有READ UNCOMMITTED、READ
-
-
在 MySQL 中只有使用了 lnnodb 數據庫引擎的數據庫或表才支持事務
-
在事務處理可以用來維護數據庫的完整性,保證成批的 SQL 語句要么全部執行,要么全部不執行
-
事務用來管理 insert update delete 語句
MyLsam
事務的特性(ACID)
-
a 原子性(Atomicity):事務中的全部操作在數據庫中是不可分割的,要么全部完成,要么均不執行
-
b 一致性(Consistency):幾個并行執行的事務,其執行結果必須與按某一順序串行執行的結果一致
-
c 隔離性(lsolation):事務的執行不受其他事務的干擾,事務執行的中間結果對其他事務必須是透明的
-
持久性(Durability):對于任意已提交事務,系統必須保證該事務對數據庫的改變不被丟失,機試數據庫出現故障
事務的分類
扁平事務(Flat Transactions)
-
a 扁平事務是事務類型中最簡單但使用最頻繁的事務
-
在扁平事務中,所有的操作都處于同一層次,由BEGIN/START TRANSACTION 開始事務,由COMMIT/ROLLBACK 結束,且都是原子的,要么都執行,要么都回滾
-
c 扁平事務是應用程序成為原子操作的基本組成模塊
什么是鏈事務
-
a 鏈事務(Chained Transaction)是指一個事物由多個子事務鏈式組成
-
b 前一個子事務的提交操作和下一個子事務的開始操作合并成一個原子操作,這意味著下一個事務將看到上一個事物的結果,就好像在事務中進行的一樣
-
c 在提交子事務時就可以釋放不需要的數據對象,而不必等到整個事務完成后才釋放
鏈事務工作示意圖

鏈事務與扁平事務的區別:
-
a 鏈事務中的回滾僅限于當前事務,相當于只能恢復到最近的一個保存點
-
b 帶保存節點的扁平事務能回滾到任意正確的保存點
-
c 帶保存節點的扁平事務中的保存點事易失的,當發生系統崩潰時,所有的保存點都將消失,這意味著當進行恢復時,事務需要從開始處重新執行
嵌套事務
什么是嵌套事務
-
a 嵌套事務(Nested Transaction)是一個層次結構框架
-
b 有一個頂層事務(top-level transaction)控制各個層次的事務
-
c 頂層事務之下嵌套的事務成為子事務(subtransaction)其控制著每一個局部的操作,子事務本身也可以是前臺事務
-
d 嵌套事務的層次結構可以看成是一棵樹
嵌套事務結構如下圖所示:

事務的隔離級別
SQL標準定義的四個隔離級別:
-
READ UNCOMMITTED:未提交讀,作用域為(global)全局、(session)當前會話

讀取未提交內容,在該隔離級別下,所有事務都可以看到其他未提交事務的執行結果
-
a 事務2查詢到的數據是事務1中修改但未提交的數據
-
b 但因為事務1回滾了數據,所以事務2查詢的數據是不正確的
-
c 因此出現了臟讀的問題
READ COMMITTED:提交讀
-
讀取提交內容。在該隔離級別下,一個事務從開始到提交之前對數據所做的改變對其它事務是不可見的,這樣就解決在READ-UNCOMMITTED級別下的臟讀問題。
-
但如果一個事務在執行過程中,其它事務的提交對該事物中的數據發生改變,那么該事務中的一個查詢語句在兩次執行過程中會返回不一樣的結果

-
事務2執行uodate語句但未提交前,事務1的前兩個select操作返回結果是相同的
-
但事務2執行commit 操作后,事務1的第三個select操作就讀取到事務2對數據的改變,導致與前兩次select操作返回不同的數據
-
因此出現了不可重復讀的問題
REPEATABLE READ:可重復讀
-
可重復讀。這是MySQL的默認事務隔離級別,能確保事務在并發讀取數據時會看到同樣的數據行,解決了READ-COMMITTED隔離級別下的不可重復讀問題
-
MySQL的InnoDB存儲引擎通過多版本并發控制(Multi_Version Concurrency Control, MVCC)機制來解決該問題
-
在該機制下,事務每開啟一個實例,都會分配一個版本號給它,如果讀取的數據行正在被其它事務執行DELETE或UPDATE操作(即該行上有排他鎖),這時該事物的讀取操作不會等待行上的鎖釋放,而是根據版本號去讀取行的快照數據(記錄在undo log中)
-
這樣,事務中的查詢操作返回的都是同一版本下的數據,解決了不可重復讀問題

-
雖然該隔離級別下解決了不可重復讀問題,但理論上會導致另一個問題:幻讀(Phantom Read)
-
正如上面所講,一個事務在執行過程中,另一個事物對已有數據行的更改
-
MVCC機制可保障該事物讀取到的原有數據行的內容相同,但并不能阻止另一個事務插入新的數據行,這就會導致該事物中憑空多出數據行,像出現了幻讀一樣,這便是幻讀問題

-
事務2對id=1的行內容進行了修改并且執行了commit操作
-
事務1中的第二個select操作在MVCC機制的作用下返回的仍是v=1的數據
-
事務3執行了insert操作
-
事務1第三次執行select操作時便返回了id=2的數據行,與前兩次的select操作返回的值不一樣
需要說明的是,REPEATABLE-READ隔離級別下的幻讀問題是SQL標準定義下理論上會導致的問題,MySQL的InnoDB存儲引擎在該隔離級別下,采用了Next-Key Locking鎖機制避免了幻讀問題。Next-Key Locking鎖機制將在后面的鎖章節中講到。
serializable:可串行讀
-
可串行化。這是事務的最高隔離級別
-
通過強制事務排序,使之不可能相互沖突,就是在每個讀的數據行加上共享鎖來實現
-
在該隔離級別下,可以解決前面出現的臟讀、不可重復讀和幻讀問題
-
但也會導致大量的超時和鎖競爭現象,一般不推薦使用。
Django 中的事務
settings.py中關于事務的兩個重要參數
ATOMIC_REQUESTS :全局控制所有的 request view是否是原子化, django默認每個request 不是原子化請求
AUTOCOMMIT : 全局控制事務是否自動提交

-
全局設置每個request當作一個原子化請求:
ATOMIC_REQUESTS = True
-
如果全局設置所有的request當作一個事務,而又不想某一個view開啟原子化事務,通過下面的設置:

-
如果ATOMIC_REQUEST 為False, 通過裝飾器,明確控制每個request 為原子化事務:

-
代碼塊方式控制些語句操作為原子化操作

事務自動提交與手動提交:
在SQL標準中,每個SQL查詢/或修改啟動一個事務,除非存在一個活躍的事務則不需要開啟新的事務,
SQL中必須顯式地提交或回滾這些事務。
這對應用程序開發人員來說并不總是方便的。為了緩解這個問題,大多數數據庫都提供了自動提交模式。
當自動提交被打開且沒有事務處于活動狀態時,每個SQL查詢將被包裝在它自己的事務中。換句話說,不僅每個這樣的查詢啟動一個事務,而且事務還會自動提交或回滾,取決于查詢是否成功。
django 默認全局是自動提交:

手動指定提交:
transaction.commit()


保存點與回滾到指定保存點

注意,必須是這種寫法回滾才生效



浙公網安備 33010602011771號