🍖事務隔離機制

一.事務隔離機制介紹

事務具備原子性、一致性、隔離性、持久性四大特性python

隔離性顧名思義指的就是事務彼此之間隔離開, 多個事務在同時處理一個數據時彼此之間互相不影響, 如若是隔離的不夠好就有可能會產生髒讀、不可重複度、幻讀等讀現象mysql

二.隔離性的四個級別

1.等級(隔離程度)由低到高

  • Read uncommitted (未提交讀)
  • Read committed (提交讀)
  • Repeatable read (可重複讀) (mysql默認)
  • Serializable (可序列化)

2.依次解決的讀現象

  • ✔ : 可能出現sql

  • ❌ : 不會出現數據庫

  髒讀 不可重複讀 幻讀
Read uncommitted
Read committed ×
Repeatable read(mysql默認) × ×
Serializable × × ×

須要強調的是 : 咱們確實能夠採用提升事務的隔離級別的方式來解決髒讀、不可重複讀、幻讀等問題, 但與此同時, 事務的隔離級別越高, 併發能力也就越低; 因此, 還須要讀者根據業務須要進行權衡session

三.四種級別介紹

1.未提交讀 (Read uncommitted)

  • 定義

是最低的隔離級別, 在這種事務隔離級別下, 一個事務能夠讀到另一個事務未提交的數據併發

  • 數據庫加鎖狀況(實現原理)

事務在讀數據的時候並未對數據加鎖spa

事務在修改數據的時候只對數據增長行級共享鎖code

  • 現象解釋

事務1讀取某行記錄時, 事務2也能對這行記錄進行讀取、更新, 而且由於事務一併未對數據增長任何鎖索引

當事務2也對該記錄進行更新時, 事務1再次讀取該記錄, 能讀到事務2對該記錄的修改版本 (由於事務2只增長了共享讀鎖, 事務1能夠再增長共享讀鎖讀取數據), 即便該修改還沒有被提交, 若此時事務2回滾, 那事務1讀到的就髒數據了, 這就引起了髒讀現象事務

事務1更新某行記錄時, 事務2不能對這行記錄作更新, 直到事務1結束 (由於事務1對數據增長了共享讀鎖, 事務2不能增長排他寫鎖進行數據的修改)

2.提交讀 (Read committed)

  • 定義

能夠理解成都已提交, 在一個事務修改數據過程當中, 若是事務還沒提交, 其餘事務不能讀該數據

  • 數據庫加鎖狀況

事務對當前被讀取的數據增長行級共享鎖(讀到時才加鎖), 一旦讀完該行, 當即釋放該行行級共享鎖

事務在更新某數據的瞬間(在更新的瞬間), 必須先對其加行級排它鎖, 直到事務結束才釋放

  • 現象解釋

事務1在讀取某行記錄的整個過程當中, 事務2均可以對該行記錄進行讀取 (由於事務一對該行記錄增長行級共享鎖的狀況下, 事務二一樣能夠對該數據增長共享鎖來讀數據)

事務1讀取某行的一瞬間, 事務2不能修改該行數據, 可是, 只要事務1讀取完改行數據, 事務2就能夠對該行數據進行修改 (事務一在讀取的一瞬間會對數據增長共享鎖, 任何其餘事務都不能對該行數據增長排他鎖; 可是事務一隻要讀完該行數據, 就會釋放行級共享鎖, 一旦鎖釋放, 事務二就能夠對數據增長排他鎖並修改數據)

事務1更新某行記錄時, 事務2不能對這行記錄作更新, 直到事務1結束 (事務一在更新數據的時候, 會對該行數據增長排他鎖, 知道事務結束纔會釋放鎖, 因此, 在事務二沒有提交以前, 事務一都能不對數據增長共享鎖進行數據的讀取; 因此, 提交讀能夠解決髒讀的現象)

3.可重複讀 (Repeatable reads)

  • 定義

因爲提交讀隔離級別會產生不可重複讀的讀現象, 因此比提交讀更高一個級別的隔離級別就能夠解決不可重複讀的問題, 這種隔離級別就叫可重複讀

  • 數據庫鎖狀況

事務在讀取某數據的瞬間 (就是開始讀取的瞬間), 必須先對其加行級共享鎖, 直到事務結束才釋放

事務在更新某數據的瞬間 (就是發生更新的瞬間), 必須先對其加行級排他鎖, 直到事務結束才釋放

  • 現象解釋

事務1在讀取某行記錄的整個過程當中, 事務2均可以對該行記錄進行讀取 (由於事務一對該行記錄增長行級共享鎖的狀況下, 事務二一樣能夠對該數據增長共享鎖來讀數據)

事務1在讀取某行記錄的整個過程當中, 事務2都不能修改該行數據 (事務一在讀取的整個過程會對數據增長共享鎖, 直到事務提交纔會釋放鎖, 因此整個過程當中, 任何其餘事務都不能對該行數據增長排他鎖; 因此, 可重複讀可以解決不可重複讀的讀現象)

事務1更新某行記錄時, 事務2不能對這行記錄作更新, 直到事務1結束 (事務一在更新數據的時候, 會對該行數據增長排他鎖, 知道事務結束纔會釋放鎖, 因此, 在事務二沒有提交以前, 事務一都能不對數據增長共享鎖進行數據的讀取; 因此, 提交讀能夠解決髒讀的現象)

4.可序列化 (Serializable)

  • 定義

是最高的隔離級別, 前面三種隔離級別都沒法解決的幻讀, 在可序列化的隔離級別中能夠解決

  • 數據庫鎖狀況

事務在讀取數據時, 必須先對其加表級共享鎖, 直到事務結束才釋放

事務在更新數據時, 必須先對其加表級排他鎖, 直到事務結束才釋放

  • 現象解釋

事務1正在讀取A表中的記錄時, 則事務2也能讀取A表, 但不能對A表作更新、新增、刪除, 直到事務1結束 (由於事務一對錶增長了表級共享鎖, 其餘事務只能增長共享鎖讀取數據, 不能進行其餘任何操做)

事務1正在更新A表中的記錄時, 則事務2不能讀取A表的任意記錄, 更不可能對A表作更新、新增、刪除, 直到事務1結束 (事務一對錶增長了表級排他鎖, 其餘事務不能對錶增長共享鎖或排他鎖, 也就沒法進行任何操做)

  • 序列化事務產生的效果
  • 沒法讀取其餘事務已經修改單位提交的記錄
  • 在當前事務完成以前, 其餘事務不能修改當前事務已經讀取的記錄
  • 在當前事務完成以前, 其餘事務插入的新記錄, 其索引鍵值不能在當前事務的任何語句所讀取的索引鍵範圍中

5.隔離級別的選擇

四種事務隔離級別從隔離程度上愈來愈高, 但同時在併發性上也就愈來愈低; 之因此有這麼幾種隔離級別, 就是爲了方便開發人員在開發過程當中根據業務須要選擇最合適的隔離級別

四.修改事務隔離級別

1.查看當前事務隔離級別

  • 能夠經過模糊匹配變量名
show variables like "%tx_isolation";

image-20210302190403075

  • 直接查看變量 tx_isolation
select @@tx_isolation;

image-20210302190600192

  • 也能夠經過如下語句查看
select @@global.tx_isolation;   # 查看全局事務隔離級別
select @@session.tx_isolation;  # 查看當前會話事務隔離級別

image-20210302190857307

ps : 在MySQL 8.0.3 中, tx_isolation 變量被 transaction_isolation 變量替換了; 在 MySQL 8.0.3 版本中查詢事務隔離級別, 只要把上述查詢語句中的 tx_isolation 變量替換成 transaction_isolation 變量便可

2.修改事務隔離級別

Mysql提供了 set transaction 語句來改變單個會話或者全局會話的事務隔離級別

set [session|global] transaction isolation level
    [read ununcommitted|read committed|repeatable read|serializable]
  • session : 表示修改的事務隔離級別將應用於當前 session(當前 cmd 窗口) 內的全部事務
  • global : 表示修改的事務隔離級別將應用於全部 session (全局) 中的全部事務, 且當前已經存在的 session 不受影響
  • 若是省略 session 和 global, 則表示修改的事務隔離級別將應用於當前 session 內的下一個還未開始的事務

3.用戶權限問題

任何用戶都能改變會話的事務隔離級別, 可是隻有擁有 super 權限的用戶才能改變全局的事務隔離級別

  • 驗證修改全局事務隔離級別, 當前會話不受影響
select @@global.tx_isolation;   # 查看全局事務隔離級別
select @@session.tx_isolation;  # 查看當前會話事務隔離級別
set global transaction isolation level read committde; 
# 修改全局事務隔離級別

image-20210302195744397

  • 能夠經過直接修改 tx_isolation 變量來修改當前 session 的事務隔離級別
set tx_isolation="read-committed";
select @@session.tx_isolation;

image-20210302204911467

---end---

相關文章
相關標籤/搜索