Mysql專題七:Mysql事務

一、事務的ACID原則

事務的概念
我們把需要保證原子性、隔離性、一致性和持久性的一個或多個數據庫操作稱之爲一個事務。

場景:小明向小強轉賬10元

  1. 原子性(Atomicity)
    轉賬操作是一個不可分割的操作,要麼轉失敗,要麼轉成功,不能存在中間的狀態,也就是轉了一半的這種情況。我們把這種要麼全做,要麼全不做的規則稱之爲原子性。
  2. 隔離性(Isolation)
    另外一個場景:
    1)小明向小強轉賬10元
    2)小明向小紅轉賬10元
    隔離性表示上面兩個操作是不能相互影響的
  3. 一致性(Consistency)
    對於上面的轉賬場景,一致性表示每一次轉賬完成後,都需要保證整個系統的餘額等於所有賬戶的收入減去所有賬戶的支出。
    如果不遵循原子性,也就是如果小明向小強轉賬10元,但是隻轉了一半,小明賬戶少了10元,小強賬戶並沒有增加,所以沒有滿足一致性了。
    同樣,如果不滿足隔離性,也有可能導致破壞一致性。
    所以說,數據庫某些操作的原子性和隔離性都是保證一致性的一種手段,在操作執行完成後保證符合所有既定的約束則是一種結果。
    實際上我們也可以對錶建立約束來保證一致性。
  4. 持久性(Durability)
    對於轉賬的交易記錄,需要永久保存。

二、事務的使用

  1. 開啓事務
    BEGIN [WORK];
    BEGIN語句代表開啓一個事務,後邊的單詞WORK可有可無。開啓事務後,就可以繼續寫若干條語句,這些語句都屬於剛剛開啓的這個事務。

  2. START TRANSACTION
    START TRANSACTION語句和BEGIN語句有着相同的功效,都標誌着開啓一個事務。

  3. 提交事務 commit
    在這裏插入圖片描述

  4. 手動中止事務 rollback
    在這裏插入圖片描述
    這裏需要強調一下,ROLLBACK語句是我們程序員手動的去回滾事務時纔去使用的,如果事務在執行過程中遇到了某些錯誤而無法繼續執行的話,事務自身會自動的回滾。

  5. 自動提交
    SHOW VARIABLES LIKE ‘autocommit’;
    在這裏插入圖片描述
    默認情況下,如果我們不顯式的使用START TRANSACTION或者BEGIN語句開啓一個事務,那麼每一條語句都算是一個獨立的事務,這種特性稱之爲事務的自動提交
    如果我們想關閉這種自動提交的功能,可以使用下邊兩種方法之一:
    • 顯式的的使用START TRANSACTION或者BEGIN語句開啓一個事務。這樣在本次事務提交或者回滾前會暫時關閉掉自動提交的功能。
    • 把系統變量autocommit的值設置爲OFF,就像這樣:SET autocommit = OFF;這樣的話,我們寫入的多條語句就算是屬於同一個事務了,直到我們顯式的寫出COMMIT語句來把這個事務提交掉,或者顯式的寫出ROLLBACK語句來把這個事務回滾掉。

  6. 隱式提交
    當我們使用START TRANSACTION或者BEGIN語句開啓了一個事務,或者把系統變量autocommit的值設置爲OFF時,事務就不會進行自動提交,但是如果我們輸入了某些語句之後就會悄悄的提交掉,就像我們輸入了COMMIT語句了一樣,這種因爲某些特殊的語句而導致事務提交的情況稱爲隱式提交,這些會導致事務隱式提交的語句包括:
    • 定義或修改數據庫對象的數據定義語言(Data definition language,縮寫爲:DDL)。所謂的數據庫對象,指的就是數據庫、表、視圖、存儲過程等等這些東西。當我們使用CREATE、ALTER、DROP等語句去修改這些所謂的數據庫對象時,就會隱式的提交前邊語句所屬於的事務。
    • 隱式使用或修改mysql數據庫中的表:當我們使用ALTER USER、CREATE USER、DROP USER、GRANT、RENAME USER、SET PASSWORD等語句時也會隱式的提交前邊語句所屬於的事務。
    • 事務控制或關於鎖定的語句:當我們在一個事務還沒提交或者回滾時就又使用START TRANSACTION或者BEGIN語句開啓了另一個事務時,會隱式的提交上一個事務。或者當前的autocommit系統變量的值爲OFF,我們手動把它調爲ON時,也會隱式的提交前邊語句所屬的事務。或者使用LOCK TABLES、UNLOCK TABLES等關於鎖定的語句也會隱式的提交前邊語句所屬的事務。
    • 加載數據的語句:比如我們使用LOAD DATA語句來批量往數據庫中導入數據時,也會隱式的提交前邊語句所屬的事務。
    • 其它的一些語句:使用ANALYZE TABLE、CACHE INDEX、CHECK TABLE、FLUSH、 LOAD INDEX INTO CACHE、OPTIMIZE TABLE、REPAIR TABLE、RESET等語句也會隱式的提交前邊語句所屬的事務。

  7. 保存點
    如果你開啓了一個事務,並且已經敲了很多語句,忽然發現上一條語句有點問題,你只好使用ROLLBACK語句來讓數據庫狀態恢復到事務執行之前的樣子,然後一切從頭再來,總有一種一夜回到解放前的感覺。所以MYSQL提出了一個保存點(英文:savepoint)的概念,就是在事務對應的數據庫語句中打幾個點,我們在調用ROLLBACK語句時可以指定會滾到哪個點,而不是回到最初的原點。定義保存點的語法如下:

    SAVEPOINT 保存點名稱;
    

    當我們想回滾到某個保存點時,可以使用下邊這個語句(下邊語句中的單詞WORK和SAVEPOINT是可有可無的):

    ROLLBACK [WORK] TO [SAVEPOINT] 保存點名稱;
    

    不過如果ROLLBACK語句後邊不跟隨保存點名稱的話,會直接回滾到事務執行之前的狀態。
    如果我們想刪除某個保存點,可以使用這個語句:

    RELEASE SAVEPOINT 保存點名稱;
    

    在這裏插入圖片描述

三、隔離性詳解

– 修改隔離級別
set session transaction isolation level read uncommitted;

– 查看隔離級別
select @@tx_isolation;
在這裏插入圖片描述

  1. 讀未提交(READ UNCOMMITTED)
    一個事務可以讀到其他事務還沒有提交的數據,會出現髒讀。

  2. 讀已提交(READ COMMITTED)
    一個事務只能讀到另一個已經提交的事務修改過的數據,並且其他事務每對該數據進行一次修改並提交後,該事務都能查詢得到最新值,會出現不可重複讀、幻讀。

  3. 可重複讀(REPEATABLE READ)
    一個事務第一次讀過某條記錄後,即使其他事務修改了該記錄的值並且提交,該事務之後再讀該條記錄時,讀到的仍是第一次讀到的值,而不是每次都讀到不同的數據,這就是可重複讀,這種隔離級別解決了不可重複,但是還是會出現幻讀。
    在這裏插入圖片描述

  4. 串行化(SERIALIZABLE)
    以上3種隔離級別都允許對同一條記錄同時進行讀-讀、讀-寫、寫-讀的併發操作,如果我們不允許讀-寫、寫-讀的併發操作,可以使用SERIALIZABLE隔離級別,這種隔離基金因爲對同一條記錄的操作都是串行的,所以不會出現髒讀、幻讀等現象。

髒讀
一個事務讀到了另一個未提交事務修改過的數據,這就是髒讀。
在這裏插入圖片描述
不可重複讀
執行一個方法首先查詢一遍得到結果A,其他事務繼而執行一個修改操作,數據庫結果變成了B,其實有的寫需求希望得到的還是A,因爲這是一個事務,不能查閱出兩個結果。
在這裏插入圖片描述
幻讀
如果一個事務先根據某些條件查詢出一些記錄,之後另一個事務又向表中插入了符合這些條件的記錄,原先的事務再次按照該條件查詢時,能把另一個事務插入的記錄也讀出來,這就是幻讀。
在這裏插入圖片描述
總結
注意:這四種隔離級別是SQL的標準定義,不同的數據庫會有不同的實現,特別需要注意的是MySQL在REPEATABLE READ隔離級別下,是可以禁止幻讀問題的發生的。
在這裏插入圖片描述

四、版本鏈

對於使用InnoDB存儲引擎的表來說,它的聚簇索引記錄中都包含兩個必要的隱藏列(row_id並不是必要的,我們創建的表中有主鍵或者非NULL唯一鍵時都不會包含row_id列):
• trx_id:每次對某條記錄進行改動時,都會把對應的事務id賦值給trx_id隱藏列。
• roll_pointer:每次對某條記錄進行改動時,這個隱藏列會存一個指針,可以通過這個指針找到該記錄修改前的信息。
在這裏插入圖片描述

五、ReadView

對於使用READ UNCOMMITTED隔離級別的事務來說,直接讀取記錄的最新版本就好了,對於使用SERIALIZABLE隔離級別的事務來說,使用加鎖的方式來訪問記錄。對於使用READ COMMITTED和REPEATABLE READ隔離級別的事務來說,就需要用到我們上邊所說的版本鏈了,核心問題就是:需要判斷一下版本鏈中的哪個版本是當前事務可見的。
ReadView中主要包含4個比較重要的內容:
1)m_ids:表示在生成ReadView時當前系統中活躍的讀寫事務的事務id列表。
2)min_trx_id:表示在生成ReadView時當前系統中活躍的讀寫事務中最小的事務id,也就是m_ids中的最小值。
3)max_trx_id:表示生成ReadView時系統中應該分配給下一個事務的id值。
4)creator_trx_id:表示生成該ReadView的事務的事務id。

READ COMMITTED的實現方式
每次讀取數據前都生成一個ReadView
REPEATABLE READ實現方式
在第一次讀取數據時生成一個ReadView

六、MVCC總結

MVCC(Multi-Version Concurrency Control ,多版本併發控制)指的就是在使用READ COMMITTD、REPEATABLE READ這兩種隔離級別的事務在執行普通的SEELCT操作時訪問記錄的版本鏈的過程。可以使不同事務的讀-寫、寫-讀操作併發執行,從而提升系統性能。READ COMMITTD、REPEATABLE READ這兩個隔離級別的一個很大不同就是:生成ReadView的時機不同,READ COMMITTD在每一次進行普通SELECT操作前都會生成一個ReadView,而REPEATABLE READ只在第一次進行普通SELECT操作前生成一個ReadView,之後的查詢操作都重複使用這個ReadView就好了。

以上均爲魯班學院學習資料,歡迎大家報班學習,真心推薦

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章