事務的隔離級別與所帶來的問題

1、事務的基本要素(ACID)

  一、原子性(Atomicity):事務開始後全部操做,要麼所有作完,要麼所有不作,不可能停滯在中間環節。事務執行過程當中出錯,會回滾到事務開始前的狀態,全部的操做就像沒有發生同樣。也就是說事務是一個不可分割的總體,就像化學中學過的原子,是物質構成的基本單位。mysql

   二、一致性(Consistency):事務開始前和結束後,數據庫的完整性約束沒有被破壞 。好比A向B轉帳,不可能A扣了錢,B卻沒收到。sql

   三、隔離性(Isolation):同一時間,只容許一個事務請求同一數據,不一樣的事務之間彼此沒有任何干擾。好比A正在從一張銀行卡中取錢,在A取錢的過程結束前,B不能向這張卡轉帳。數據庫

   四、持久性(Durability):事務完成後,事務對數據庫的全部更新將被保存到數據庫,不能回滾。session

2、SQL標準的事務隔離級別(mysql默認爲可重複讀,oracle默認爲讀已提交)

  • 讀未提交(read uncommitted)是指,一個事務還沒提交時,它作的變動就能被別的事務看到。
  • 讀已提交(read committed)是指,一個事務提交以後,它作的變動纔會被其餘事務看到。
  • 可重複讀(repeatable read)是指,一個事務執行過程當中看到的數據,老是跟這個事務在啓動時看到的數據是一致的。固然在可重複讀隔離級別下,未提交變動對其餘事務也是不可見的。
  • 串行化(serializable ),顧名思義是對於同一行記錄,「寫」會加「寫鎖」,「讀」會加「讀鎖」。當出現讀寫鎖衝突的時候,後訪問的事務必須等前一個事務執行完成,才能繼續執行。

例子併發

事務一 事務二
啓動事務A,查詢A=10 啓動事務B
查詢A=10, 更新A=20
查詢值a1
提交事務B
查詢值a2
提交事務A
查詢值a3
  • 若隔離級別是「讀未提交」, 則a1的值就是20,雖然B沒提交2可是結果已經A看到了oracle

  • 若隔離級別是「讀已提交」,則a1是10,a2的值是2。事務B的更新在提交後才能被A看到。因此, a3的值也是2。性能

  • 若隔離級別是「可重複讀」,則a一、a2是10,a3是20。之因此a2仍是10,遵循的就是這個要求:事務在執行期間看到的數據先後必須是一致的。.net

  • 若隔離級別是「串行化」,則在事務B執行「將A=10改爲20」的時候,會被鎖住。直到事務A提交後,事務B才能夠繼續執行。因此從A的角度看, a一、a2值是10,a3的值是20線程

3、如何設置和查看隔離級別

  • 讀未提交:read uncommitted
  • 讀已提交:read committed
  • 可重複讀:repeatable read
  • 串行化:serializable

查看隔離級別日誌

show variables like 'transaction_isolation';

設置innodb的事務級別方法是:set 做用域 transaction isolation level 事務隔離級別,例如~

SET [SESSION | GLOBAL] TRANSACTION ISOLATION LEVEL {READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE}

set global transaction isolation level read committed; //全局的

set session transaction isolation level read committed; //當前會話

4、事務隔離級別所帶來的問題

img

這四種隔離級別採起不一樣的鎖類型來實現,若讀取的是同一個數據的話,就容易發生問題。例如:

​ 髒讀(Drity Read):某個事務已更新一份數據,另外一個事務在此時讀取了同一份數據,因爲某些緣由,前一個RollBack了操做,則後一個事務所讀取的數據就會是不正確的。

​ 不可重複讀(Non-repeatable read):在一個事務的兩次查詢之中數據不一致,這多是兩次查詢過程當中間插入了一個事務更新的原有的數據。

​ 幻讀(Phantom Read):在一個事務的兩次查詢中數據筆數不一致,例若有一個事務查詢了幾列(Row)數據,而另外一個事務卻在此時插入了新的幾列數據,先前的事務在接下來的查詢中,就會發現有幾列數據是它先前所沒有的。

解決方案

//todo

補充

  • 事務隔離的實現:每條記錄在更新的時候都會同時記錄一條回滾操做。同一條記錄在系統中能夠存在多個版本,這就是數據庫的多版本併發控制(MVCC)。

  • 回滾日誌何時刪除?系統會判斷當沒有事務須要用到這些回滾日誌的時候,回滾日誌會被刪除。

  • 何時不須要了?當系統裏麼有比這個回滾日誌更早的read-view的時候。

  • 爲何儘可能不要使用長事務。長事務意味着系統裏面會存在很老的事務視圖,在這個事務提交以前,回滾記錄都要保留,這會致使大量佔用存儲空間。除此以外,長事務還佔用鎖資源,可能會拖垮庫。

  • 事務啓動方式:

    • 1、顯式啓動事務語句,begin或者start transaction,提交commit,回滾rollback;
    • 2、set autocommit=0,該命令會把這個線程的自動提交關掉。這樣只要執行一個select語句,事務就啓動,並不會自動提交,直到主動執行commit或rollback或斷開鏈接。
    • 建議使用方法一,若是考慮多一次交互問題,可使用commit work and chain語法。在autocommit=1的狀況下用begin顯式啓動事務,若是執行commit則提交事務。若是執行commit work and chain則提交事務並自動啓動下一個事務。

1、事務隔離級別爲讀提交時,寫數據只會鎖住相應的行

  2、事務隔離級別爲可重複讀時,若是檢索條件有索引(包括主鍵索引)的時候,默認加鎖方式是next-key 鎖;若是檢索條件沒有索引,更新數據時 會鎖住整張表。一個間隙被事務加了鎖,其餘事務是不能在這個間隙插入記錄的,這樣能夠防止幻讀。

  三、事務隔離級別爲串行化時,讀寫數據都會鎖住整張表

   4、隔離級別越高,越能保證數據的完整性和一致性,可是對併發性能的影響也越大。****

   5、MYSQL MVCC實現機制參考連接:https://blog.csdn.net/whoamiyang/article/details/51901888****

   6、關於****next-key 鎖能夠參考連接:https://blog.csdn.net/bigtree_3721/article/details/73731377********

相關文章
相關標籤/搜索