對事務的理解

寄曇說發表於2019-06-19

什麼是事務?

事務是資料庫管理系統執行過程中的一個邏輯單位,由一個有限的資料庫操作序列構成。事物的操作要麼完全地執行,要麼完全地不執行。

在關聯式資料庫中,一個事務可以是一條SQL語句,一組SQL語句或整個程式。事務有ACID四個特性:

1、原子性(Atomicity):即不可分割,要麼全部執行,要麼全部不執行。事務的正確執行會使資料庫從一種狀態轉換成另一種狀態,所以如果事務的所有的子事務都提交成功,那麼事務成功執行,資料庫狀態發生變化;如果事務中的任何一個子事務提交失敗,那麼事務失敗,之前所有執行的子事務都會被回滾,資料庫回到事務執行前的狀態

2、一致性(consistency):事務的執行必須是使資料庫從一種正確的狀態轉移到另外一種正確的狀態

3、隔離性(isolation):在事務完全執行成功之前,不對其他的事務產生影響,也不會受到其他事務的影響

4、永續性(durability):即事務在成功提交後,他對資料庫的改變是永久的,即使資料庫發生災難性的故障,也能夠通過資料庫操作日誌和資料備份找回原有的資料。

 

事務的作用

資料庫的事務:

1、他能夠為資料庫操作提供了一個從失敗恢復到正常狀態的方法

2、當多個應用程式併發訪問資料庫時,能夠在這些應用程式提供一個隔離方法,能夠防止各個應用之間的操作互相干擾

系統的事務:

1、對業務進行一系列的操作時,要麼全部執行,要麼全部不執行

 

事務在併發情況下帶來的問題

事務在為資料庫操作帶來很多便利的同時,也帶來了許多問題。

1、髒讀(針對未提交資料):事務A對某一條資料進行了操作,但是並未提交,此時事務B讀取到了事務A還未提交的操作後的該條資料,如果事務A發生回滾,事務B讀到的資料就是錯誤的,這種現象被稱為髒讀

具體例子:灰太狼檢視自己家裡銀行卡里的存款(卡里擁有5000元),灰太狼檢視存款(事務A開啟),同時紅太狼進行取款(事務B開啟),取走1000元(事務B並未提交),此時灰太狼檢視到的存款為4000元(檢視到了紅太狼取完款後的銀行卡餘額,事務A結束),但是紅太狼又將1000元存回去(事務B結束),實際上此時卡里還有5000元,但是灰太狼誤以為只有4000元,這就是一種典型的髒讀現象。

2、不可重複讀(針對其他事物提交前後,讀取資料本身的對比):事務A讀取到了某一條資料,然後事務A執行他的邏輯,此時事務B修改了該條資料,事務A再次讀取到該條資料時,發現和第一次讀取到的資料不一致,這種現象被稱為不可重複讀

具體例子:灰太狼檢視自己家裡銀行卡里的存款(卡里擁有5000元),灰太狼檢視存款(事務A開啟),檢視到存款為5000元,同時紅太狼進行取款(事務B開啟),取走1000元(事務B結束),然後灰太狼再次檢視存款為4000元(事務A結束),在同一個事務內兩次讀到的銀行卡餘額不同,這就是一種典型的不可重複讀現象。

3、幻讀(針對其他事物提交前後,讀取資料條數的對比):事務A讀取到了符合一個條件的某幾條(N條)資料,事務B增添了符合該條件的(M條)幾條資料,並提交,事務A再次讀取符合該條件的資料時,讀到的條數為(N+M條)與第一次讀取到的條數不相等,這種現象被稱為幻讀

具體例子:灰太狼抓到了幾隻羊,出門買調料前,數了一遍鍋裡的羊(事務A開啟),有3只,就出門了。灰太狼出門後紅太狼又從羊村抓了2只羊回來放到鍋裡(事務B),灰太狼回家後數了一下鍋裡的羊,有5只羊,灰太狼還以為自己第一次數錯了,這便是一種典型的幻讀現象。

 

事務的隔離級別

事務的隔離級別擁有四種:

1、Read Uncommitted(讀未提交):事務修改資料後即使未提交,其他事務也可以讀取到該事務修改後未被提交的資料,所以這個級別的隔離機制無法解決髒讀、不可重複讀、幻讀中的任何一種

2、Read Committed (讀已提交):能夠讀取到那些已經提交的資料,能夠防止髒讀,但是無法解決不可重複讀和幻讀的問題

3、Repeatable Read(重複讀):在資料讀取出來後對其加鎖,防止別人修改他,即讀取了一條資料,改事務不結束,別的事務就不能修改這條記錄,能夠解決髒讀、不可重複讀的問題,但是幻讀依舊解決不了

4、Serializable(序列化):最高階別的事務隔離級別,不管擁有多少事務,只有執行完一個完整的事務後才能執行下一個事務,這樣能夠避免髒讀、不可重複讀、幻讀的問題

 

事務的隔離級別設定的越高,事務對資料進行操作的行為就越安全,但是安全的代價是事務執行效率的降低,所以事務的隔離級別並不是設定的越高越好,實際開發中我們需要在安全性和執行效率之間做一個權重比

 

檢視事務的隔離級別以及修改的命令

 檢視mysql事務隔離級別命令

檢視會話當前隔離級別:SELECT @@TX_ISOLATION;

檢視系統當前隔離級別:SELECT @@GLOBAL.TX_ISOLATION;

修改會話當前的隔離級別:SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE; (READ UNCOMMITTED || READ COMMITTED || REAPEATABLE READ)

修改系統當前的隔離級別:SET GLOBAL TRANSACTION ISOLATION LEVEL SERIALIZABLE;(READ UNCOMMITTED || READ COMMITTED || REAPEATABLE READ)

 

注:作為入坑不久的小白,第一次寫部落格,如有不對的地方,請指出,謝謝!

 

相關文章