您好,登錄后才能下訂單哦!
這篇“mysql的事務隔離級別是什么”文章的知識點大部分人都不太理解,所以小編給大家總結了以下內容,內容詳細,步驟清晰,具有一定的借鑒價值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來看看這篇“mysql的事務隔離級別是什么”文章吧。
事務隔離級別有四個:1、Read Uncommitted(讀取未提交),允許讀取尚未提交的數據變更,可能造成臟讀、不可重復讀、幻讀。2、Read Committed(讀取已提交),允許讀取并發事務已經提交的數據,可以避免臟讀,但是可能造成不可重復、幻讀。3、Repeatable Read(可重復讀取),對同一字段多次讀取的結果都是一致。4、Serializable(可串行化)。
事務是邏輯上的一組操作,要么全執行,要么全不執行。
事務最經典栗子也經常被拿出來的栗子就是銀行轉賬了。比如小明要給小紅轉賬1000元,這個轉賬會涉及到兩個關鍵操作:將小明的余額減1000元,將小紅的余額減1000元。萬一這兩個操作之間突然出現錯誤,導致小明余額減少但是小紅余額沒有增加,這種情況是肯定不允許的。事務就是保證這兩個關鍵操作要么都成功,要么都不成功。
**原子性:**事務最小的執行單位,不允許分割。事務的原子性確保動作要么全部執行,要么全部不執行。
**一致性:**執行事務的前后,數據保持一致。例如轉賬的業務中,無論事務是否成功,轉賬者和收款人的總額應該是不變的。
**隔離性:**并發訪問數據庫時,一個用戶的事務不應該被其他事務所影響,各并發事務之間數據庫是獨立的。
**持久性:**一個事務被提交后,它對數據庫中數據的改變是持久的,即使數據庫發生故障也不應該對其有影響。
在典型的應用程序中,多個事務并發運行,經常會操作相同的數據來完成各自的任務(多個用戶對同一數據進行操作)。并發雖然是必須的,但是可能會帶來以下的問題:
**臟讀(Dirty read):**當一個事務正在訪問數據并且對其進行了修改,但是還沒提交事務,這時另外一個事務也訪問了這個數據,然后使用了這個數據,因為這個數據的修改還沒提交到數據庫,所以另外一個事務讀取的數據就是“臟數據”,這種行為就是“臟讀”,依據“臟數據”所做的操作可能是會出現問題的。
修改丟失(Lost of modify):是指一個事務讀取一個數據時,另外一個數據也訪問了該數據,那么在第一個事務修改了這個數據之后,第二個事務也修改了這個數據。這樣第一個事務內的修改結果就被丟失,這種情況就被稱為修改丟失。例如:事務1讀取表中數據A=20
,事務2也讀取A=20
,事務1修改A=A-1
,事務2也修改A=A-1
,最終結果都是19
,但是事務1的修改記錄丟失了。
不可重復讀(Unrepeatableread):指在一個事務內多次讀取同一數據,在這個事務還沒結束時,另外一個事務也訪問了這個數據并對這個數據進行了修改,那么就可能造成第一個事務兩次讀取的數據不一致,這種情況就被稱為不可重復讀。
幻讀(Phantom read):幻讀與不可重復讀類似,幻讀是指一個事務讀取了幾行數據,這個事務還沒結束,接著另外一個事務插入了一些數據,在隨后的查詢中,第一個事務讀取到的數據就會比原本讀取到的多,就好像發生了幻覺一樣,所以稱為幻讀。
不可重復讀的重點是修改,幻讀的重點是新增或者刪除。
栗子1(同樣的條件,你讀取過的數據,再次讀取的時候不一樣了):事務1中的A先生讀取自己的工資是1000的操作還沒結束,事務2的B先生就修改了A先生的工資為2000,A先生再次讀取自己工資的時候就變成2000了,這就是不可重復讀。
栗子2(同樣的條件,第1次和第2次讀取出來的記錄條數不一樣):假如某工資表中工資大于3000的有4人,事務1讀取了所有工資大于3000的人,總共查詢到4條記錄,這是事務2又查詢了一條工資大于3000的記錄,事務1再次讀取查詢到的記錄就是5條了,這就是幻讀。
SQL標準定義了四個隔離級別:
**讀取未提交(READ-UNCOMMITTED):**最低的隔離級別,允許讀取尚未提交的數據變更,可能造成臟讀、不可重復讀、幻讀。
**讀取已提交(READ-COMMITTED):**允許讀取并發事務已經提交的數據,可以避免臟讀,但是可能造成不可重復、幻讀。
**可重復讀(REPEATABLE-READ):**對同一字段多次讀取的結果都是一致的,除非本身事務修改,可以避免臟讀和不可重復讀,但是可能造成幻讀。
**可串行化(SERIALIZABLE):**最高的隔離級別,完全服從ACID的隔離級別,所有的事務依次執行,可以避免臟讀、不可重復讀、幻讀。
隔離級別 | 臟讀 | 不可重復讀 | 幻讀 |
---|---|---|---|
讀取未提交 | √ | √ | √ |
讀取已提交 | × | √ | √ |
可重復讀 | × | × | √ |
可串行化 | × | × | × |
MySQL InnoDB
存儲引擎默認的事務隔離級別是可重復讀(REPEATABLE-READ),可以通過命令select @@tx_isolation;
語句來查看,MySQL 8.0
該語句改為SELECT @@transaction_isolation;
mysql> SELECT @@tx_isolation;
+-----------------+
| @@tx_isolation |
+-----------------+
| REPEATABLE-READ |
+-----------------+
MySQL InnoDB
存儲引擎的可重復讀并不能避免幻讀,需要應用使用加鎖讀來保證,這加鎖讀使用到的機制就是Next-Key Locks
。
因為隔離級別越低,事務請求的鎖越少,所以大部分數據庫系統的隔離級別都是讀取已提交(READ-COMMITTED),InnoDB
存儲引擎默認使用 REPEATABLE-READ(可重讀) 并不會有任何性能損失。
InnoDB
存儲引擎在分布式事務的情況下一般會用到可串行化隔離級別。
? 拓展一下(以下內容摘自《MySQL 技術內幕:InnoDB 存儲引擎(第 2 版)》7.7 章):
InnoDB存儲引擎提供了對XA事務的支持,并通過XA事務來支持分布式事務的實現。分布式事務指的是允許多個獨立的事務資源參與到一個全局的事務中。事務資源通常是關系型數據庫系統,但也可以是其他類型的資源。全局事務要求在其中的所有參與的事務要么都提交,要么都回滾,這對事務的原有ACID要求又有了提高。另外,在使用分布式事務時,InnoDB 存儲引擎的事務隔離級別必須設置為 SERIALIZABLE。
MySQL
命令行的默認配置中事務都是自動提交的,即執行SQL
語句就會馬上執行COMMIT
操作。可以用命令START TRANSACTION
開始一個事務。
我們可以通過下面命令設置事務隔離級別。
SET [SESSION|GLOBAL] TRANSACTION ISOLATION LEVEL [READ UNCOMMITTED|READ COMMITTED|REPEATABLE READ|SERIALIZABLE]
我們再來看一下我們在實際操作中使用到的一些并發控制語句:
START TRANSACTION | BEGIN
:顯示的開啟一個事務。
COMMIT
:提交事務,使得對數據庫做的所有修改成為永久性。
ROLLBACK
:回滾到結束用戶的事務,并撤銷正在進行的所有未提交的修改。
還是剛才上面的讀已提交的圖,雖然避免了讀未提交,但是卻出現了,一個事務還沒有結束,就發生了 不可重復讀問題。
演示幻讀出現的情況
sql 腳本 1 在第一次查詢工資為 500 的記錄時只有一條,sql 腳本 2 插入了一條工資為 500 的記錄,提交之后;sql 腳本 1 在同一個事務中再次使用當前讀查詢發現出現了兩條工資為 500 的記錄這種就是幻讀。
幻讀和不可重復讀有些相似之處 ,但是不可重復讀的重點是修改,幻讀的重點在于新增或者刪除。
解決幻讀的方法
將事務隔離級別調整為 SERIALIZABLE
。
在可重復讀的事務級別下,給事務操作的這張表添加表鎖。
在可重復讀的事務級別下,給事務操作的這張表添加 Next-Key Locks
。
說明:
Next-Key Locks
相當于 行鎖 + 間隙鎖
以上就是關于“mysql的事務隔離級別是什么”這篇文章的內容,相信大家都有了一定的了解,希望小編分享的內容對大家有幫助,若想了解更多相關的知識內容,請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。