關於mysql事務隔離級別MVCC多版本控制的一個疑問?
補充:
題主在評論里補充了問題,疑問應該是讀寫事務同時操作一個page的時候,比如page里有3行數據,主鍵分別是1,6,28,這裡其實是不會有問題的,B+樹的每個節點有一個latch(比如pthread_rwlock_t),讀的時候會調用fix_page(page_id,read),寫的時候會調用fix_page(page_id,write),會對page加上讀或寫latch,這個latch跟並發控制里的鎖不一樣,是為了保護B+樹這個節點,只有讀完成以後,寫才會進去,所以不會有讀到一半,被更新的情況。latch的時間與行鎖,表鎖等比起來,是非常短的,從並發控制的角度來看,一般認為這不算是阻塞
&" data-caption="" dw="411" dh="192" class="content_image lazy" w="411" data-actualsrc="//i1.wp.com/pic1.zhimg.com/50/v2-379a934f119c2f0ba2d3e535f799cc83_hd.jpg">原答案:
其實我之前也有類似的困惑,百思不得其解,閱讀了大量的論文,代碼,向組裡的大神同事@韓富晟 請教後才徹底明白。下面我用一個簡單的模型來解釋一下這個問題,讀寫確實有可能不是100%不阻塞的
有以下幾個角色:
1.一行數據row
2.管理號管理器,負責分配版本號
3.讀事務,讀一行數據
4.寫事務,寫一行數據
5.針對row的幾個修改,其中version=2和version=5的修改是歷史修改
讀事務在開始時會向版本號管理器去拿一個版本,作為snapshot version,它希望能夠讀到小於snapshot version的最新版本的數據。
寫事務將修改存到一個新的結點裡,並將結點鏈到row和舊的修改結點上,commit之前會去拿一個commit version
那麼現在根據寫事務的commit version的大小會有以下幾種情況:
1.寫事務還沒有獲得commit version,那麼讀事務可以直接跳過這個結點,直接讀下一個結點,發現下一個結點的版本號5&<8,便可以讀這個版本的數據。可以直接跳過的原因是,版本號管理器是遞增分配版本號的,因此寫事務後面獲得的版本號一定大於snapshot version,讀事務一定不需要讀這個版本,這種情況下讀寫是完全不阻塞的。
2.寫事務已經獲得commit version,並且commit version大於snapshot version,並且已經填寫到結點裡,這種情況也可以直接跳過這個結點。
3.寫事務已經獲得commit version,並且commit version小於snapshot version,但是結點裡可能還沒有來得及填這個version,因為一個事務可能會修改很多行,填version需要一定的時間,這個時候讀事務就需要等一下,直到確定了commit version之後才知道到底能不能讀
&" data-caption="" dw="493" dh="480" class="origin_image zh-lightbox-thumb lazy" w="493" data-original="https://pic2.zhimg.com/v2-71351ef3ef10505cc57c971ba3421afe_r.jpg" data-actualsrc="//i1.wp.com/pic2.zhimg.com/50/v2-71351ef3ef10505cc57c971ba3421afe_hd.jpg">謝邀。
MySQL底層引擎(InnoDB/TokuDB)的寫操作不會阻塞讀操作。拿TokuDB為例,當client1執行:
c1&> begin;c1&> update t1 set age=21 where id=2;這裡的update操作,引擎首先會拿一個row lock:https://github.com/XeLabs/ft-index/blob/master/src/ydb_write.cc#L283https://github.com/XeLabs/ft-index/blob/master/src/ydb_row_lock.cc#L178目的是防止另外的一個事務更新同一行。現在有個client2執行:c2&> select * from t1 where id=2;
這個操作不會受c1的row lock所限制,直接從MVCC里讀取相應的版本,具體讀到什麼是由隔離級別和自身的事務ID決定的,如果是READ-UNCOMMITTED,那c2可以看到c1的更新,如果是READ-COMMITTED或更高則看不到。MySQL storage engine MVCC主要用來做事務版本控制,並發其次。
推薦閱讀: