MySQL為什麼可以解決髒讀和不可重複讀?

2021-02-19 琉憶編程庫

一般是通過鎖機制,解決掉不可重複讀和幻讀的問題。是不是可以通過樂觀鎖的問題去解決不可重複讀和幻讀的問題,MySQL 採用的是 MVCC 機制來解決髒讀、不可重複讀的問題。

MVCC 英文全稱是 Muitiversion Concurrency Control,多版本並發控制技術,原理是通過數據行的多個版本管理實現資料庫的並發控制,通過保存數據的歷史版本,可以通過比較版本號決定數據是否顯示,讀取數據的時候不需要加鎖保證事務的隔離效果。

MVCC 是如何解決髒讀的?

MVCC 解決了一致性讀問題,當我們讀取某個資料庫在時間點的快照時,只能看到時間點之前提交更新的結果,不能看到時間點之後事務提交的更新結果。這樣就避免了髒讀問題。

MVCC 是如何解決不可重複讀的?

在說如何解決不可重複讀之前,先談談 MVCC 的實現原理。

快照讀

快照讀,讀取的是快照數據,一般不加鎖的 select 查詢都是快照讀。

select * from player where ...

當前讀

當前讀就是讀的最新數據,而不是歷史數據,加鎖的 select,或者對數據進行增刪改都會讀取當前最新數據。

SELECT * FROM player LOCK IN SHARE MODE;
SELECT FROM player FOR UPDATE;
INSERT INTO player values ...
DELETE FROM player WHERE ...
UPDATE player SET ...

MVCC 是基於 Read View + 活躍事務表實現的。

行記錄快照模型

數據表中的一行記錄實際上有多個版本,每個版本有自己的事務 ID(row_trx_id)每次需要讀取那個版本數據的時候,是通過當前版本,加 Undo Log 中存儲的快照鍊表得到那個版本真實數據。

行記錄快照是保存在 Undo Log 中,並且行記錄快照是通過鍊表串聯起來,每個快照都保存了 trx_id (事務 ID),如果要找到歷史快照,只需要遍歷回滾指針進行查找。

Read View

會有這麼一個問題:一個事務開啟,這個事務要查詢數據,需要讀取哪個版本的行記錄呢?Read View 就是來解決這個問題的,簡單的說 Read View 是可以幫助我們解決可見性問題的。

ReadView 中保存了當前活躍的事務列表。通過比較事務版本,可以判斷當前行數據版本是不是對當前事務可見。

Read View 模型

如果當前行記錄版本是 trx_id < 活躍的最小事務 ID (up_limit_id),說明行記錄在這些活躍的事務創建前就已經提交,這個行記錄對當前事務是可見的。

如果當前行記錄事務版本 trx_id > 活躍的最大事務 ID (low_limit_id) 說明,這個行記錄是在事務後創建的,這個行記錄對當前事務不可見。

如果 up_limit_id < trx_id < low_limit_id,則有如下情況:

若 row trx_id 在數組 trx_ids 中,表示這個版本是由還沒提交的事務生成的,不可見。

若 row trx_id 不在數組 trx_ids 中,表示這個版本是已經提交了的事務生成的,可見。

相關焦點

  • MySQL面試題:ACID及髒讀,不可重複讀和幻讀-開課吧
    最經典的就是轉帳案例,我們把轉和轉出當作個事物的話,就需要在SQL中顯式指定開啟事務。致性是說資料庫事務不能破壞關係數據的完整性以及業務邏輯上的致性 。我們可以從資料庫層和業務層兩來保證,資料庫層我們可以設置觸發器,外鍵,表,約束等來保證,業務層就是我們Java程師的作啦。
  • 來談談MySQL事務及事務引發的問題
    不可重複讀和髒讀的區別是,髒讀是讀取前一事務未提交的髒數據,不可重複讀是重新讀取了前一事務已提交的數據。很多人認為這種情況就對了,無須困惑,當然是後面的為準。未授權讀取(Read Uncommitted)也稱為讀未提交(Read Uncommitted):會引發髒讀取、不可重複讀和虛讀,但避免了更新丟失。如果一個事務已經開始寫數據,則另外一個事務則不允許同時進行寫操作,但允許其他事務讀此行數據。該隔離級別可以通過「排他寫鎖」實現。
  • 初中級必須知道的MYSQL經典面試題
    在我們平時面試過程中,那些mysql面試題是經常被問到的呢?你有哪些問題是不會的呢?趁熱打鐵趕緊鞏固一下mysql的知識吧1.mysql事務的基本特徵和事務隔離級別四大特性:原子性,一致性,隔離性,持久性;隔離級別:讀未提交,不可以重複讀,可重複讀,串行化。
  • 解決MySQL可重複讀——詳解間隙鎖
    間隙鎖(Gap Lock)是Innodb在可重複讀提交下為了解決幻讀問題時引入的鎖機制,(下面的所有案例沒有特意強調都使用可重複讀隔離級別)幻讀的問題存在是因為新增或者更新操作,這時如果進行範圍查詢的時候(加鎖查詢),會出現不一致的問題,這時使用不同的行鎖已經沒有辦法滿足要求,需要對一定範圍內的數據進行加鎖,間隙鎖就是解決這類問題的。
  • MySql面試題及答案大全
    事務的隔離級別,mysql默認的隔離級別是什麼?讀未提交(Read uncommitted),一個事務可以讀取另一個未提交事務的數據,最低級別,任何情況都無法保證。讀已提交(Read committed),一個事務要等另一個事務提交後才能讀取數據,可避免髒讀的發生。
  • 共享鎖、排他鎖、互斥鎖、悲觀鎖、樂觀鎖、行鎖、表鎖、頁面鎖、不可重複讀、丟失修改、讀髒數據
    共享鎖(S鎖): 又稱為讀鎖,可以查看但無法修改和刪除的一種數據鎖。如果事務T對數據A加上共享鎖後,則其他事務只能對A再加共享鎖,不能加排它鎖。獲準共享鎖的事務只能讀數據,不能修改數據。 共享鎖下其它用戶可以並發讀取,查詢數據。但不能修改,增加,刪除數據。資源共享.
  • 陌陌面試官:談談你對MySQL中事務和鎖的理解?
    不可重複讀(Non-Repeatable Read) 不可重複讀指的是在一個事務執行過程中,讀取到其它事務已提交的數據,導致兩次讀取的結果不一致。不可重複讀和幻讀的區別在於不可重複讀是讀到的是其他事務修改或者刪除的數據,而幻讀讀到的是其它事務新插入的數據。髒寫的問題太嚴重了,任何隔離級別都必須避免。其它無論是髒讀,不可重複讀,還是幻讀,它們都屬於資料庫的讀一致性的問題,都是在一個事務裡面前後兩次讀取出現了不一致的情況。# 四種隔離級別在SQL標準中設立了4種隔離級別,用來解決上面的讀一致性問題。
  • MySQL中的幻讀,你真的理解嗎?
    昨天接到阿里的電話面試,對方問了一個在MySQL當中,什麼是幻讀。當時一臉懵逼,憑著印象和對方胡扯了幾句。面試結束後,趕緊去查資料,才發現之前對幻讀的理解完全錯誤。下面,我們就聊聊幻讀。要說幻讀,就要從MySQL的隔離級別說起。
  • MySQL中的當前讀
    前言我們知道髒讀、不可重複讀、幻讀的概念和區別,也知道事務的四種隔離級別:讀未提交、讀已提交、可重複讀、串行化的含義。如果你對這些概念仍然有疑問,關注我,在主頁中找到之前分享的文章:MySQL中的事務的理解。
  • MYSQL面試常考知識點總結
    此時,將提 交數據的版本數據與資料庫表對應記錄的當前版本信息進行比對,如果提交的數據 版本號大於資料庫表當前版本號,則予以更新,否則認為是過期數據髒讀、虛讀和不可重複讀     髒讀:一個事務讀取到了另外一個事務沒有提交的數據;(修改的數據還未提交就被另一個事務使用這個數據
  • 阿里面試:說說一致性讀實現原理?
    事務的並發問題不可重複度:事務A多次讀取同一份數據,事務B在此過程中對數據修改並提交,導致事務A多次讀取同一份數據的結果不一致。幻讀:事務A修改數據的同時,事務B插入了一條數據,當事務A提交後發現還有數據沒被修改,產生了幻覺。不可重複讀側重於update操作,幻讀側重於insert或delete。
  • 一文講清楚MySQL事務隔離級別和實現原理,開發人員必備知識點
    採用哪種隔離級別要根據系統需求權衡決定,其中,可重複讀是 MySQL 的默認級別。事務隔離其實就是為了解決上面提到的髒讀、不可重複讀、幻讀這幾個問題,下面展示了 4 種隔離級別對這三個問題的解決程度。只有串行化的隔離級別解決了全部這 3 個問題,其他的 3 個隔離級別都有缺陷。
  • 萌新和小白都能看懂的MySQL事務機制
    事務並發產生的問題髒讀,讀到了其他事務還沒提交的數據不可重複讀,讀到了其他事務提交之後的數據,數據變化了(update/delete)幻讀,讀到了其他事務提交之後的數據,只有數據增加了行才叫幻讀(insert)你可能會說,事務不是有隔離性嗎,為什麼還有這麼多問題?
  • MySQL 三萬字精華總結 + 面試100 問,吊打面試官綽綽有餘(收藏系列)
    「髒讀」 、 「不可重複讀」和「幻讀」 ,其實都是資料庫讀一致性問題,必須由資料庫提供一定的事務隔離機制來解決:一種是加鎖:在讀取數據前,對其加鎖,阻止其他事務對數據進行修改。從用戶的角度來看,好象是資料庫可以提供同一數據的多個版本。事務隔離級別資料庫事務的隔離級別有4種,由低到高分別為READ-UNCOMMITTED(讀未提交): 最低的隔離級別,允許讀取尚未提交的數據變更,可能會導致髒讀、幻讀或不可重複讀。READ-COMMITTED(讀已提交): 允許讀取並發事務已經提交的數據,可以阻止髒讀,但是幻讀或不可重複讀仍有可能發生。
  • 面試官:你說對 MySQL 事務很熟?那我問你 10 個問題
    什麼是髒讀、不可重複讀、幻讀髒讀在事務A修改數據之後提交數據之前,這時另一個事務B來讀取數據,如果不加控制,事務B讀取到A修改過數據,之後A又對數據做了修改再提交,則B讀到的數據是髒數據,此過程稱為髒讀Dirty Read。
  • MySQL的事務隔離級別是什麼?
    還拿轉帳為例,如果A手裡有100元,轉給B120元,顯然A手裡的錢不夠扣,假如你給金額這一列設置了不能小於0的約束,那麼在事務執行的時候監測到約束沒被滿足,就會回滾,這時可以說事務保證了一致性。同樣的,如果你沒有添加約束,而是在業務層做了校驗,並做了回滾,那麼也可以說事務保證了一致性。那如果資料庫和業務層都沒有做約束呢,A的錢不就變為負數了嗎?
  • Mysql事務知識點
    在讀未提交下,會產生髒讀的問題。還是以上面的場景為例,事務1查詢出來的結果為(1, lis),解決了髒讀的問題,但同時又引出了不可重複讀的問題,考慮下面的場景:1內對同樣一條記錄的兩次讀操作讀到的結果不一致,這種問題即不可重複讀。
  • 面試官:談談你對MySQL事務的認識?
    這篇文章屬於mysql資料庫系列,我們來談談事務方面的常見面試題。那麼,具體題目有下面這些:1、講講為什麼用事務?事務的四大特性?事務的隔離級別知道吧,你們生產用哪種?2、Innodb中ACID具體是如何實現的?3、redo log和binlog的一致性如何保證?4、大事務有哪些壞處?生產上遇到過大事務麼?你怎麼排查和解決的?
  • MySQL學習之mvcc原理和當前讀
    之前學習了MySQL事務隔離級別,在可重複讀的隔離級別下,如果一個事務啟動的時候,會創建一個視圖 read view,之後這個事務在執行期間,即使有其他事務修改了數據,這個事務看到的仍然和啟動時是一樣的,好像別人做的任何操作和他無關一樣。首先先了解一下事物的啟動時機和視圖概念是怎麼樣的吧。第一種啟動方式,一致性視圖是在執行第一個快照讀語句時創建的。
  • 【資料庫】MySQL進階四、select
    就是那些需要業務層面數據獨佔時,可以考慮使用for update。場景上,比如火車票訂票,在屏幕上顯示餘票,而真正進行出票時,需要重新確定一下這個數據沒有被其他客戶端修改。所以,在這個確認過程中,可以使用for update。這是統一的解決方案方案問題,需要前期有所準備。