MySql - 對事務是怎麼處理的

undo日誌鏈表

這個要從MySql - 對update是怎麼處理的的undo日誌文件提及。
咱們對數據進行修改以前,都會把數據寫入到undo日誌中,若是對一條數據作了屢次修改,那這些數據就會經過鏈表關聯起來。
MySql - 一條語句是怎麼插入磁盤的提到了一條數據的結構,咱們這裏就用DB_TRX_ID事務ID,DB_ROLL_PTR事務回滾以及具體的數據DATA來簡化一條數據,下面用簡單的例子講解一下這個undo日誌鏈表。segmentfault

步驟一:

插入一條數據DATA爲,AAA,此時的DB_TRX_ID爲1,DB_ROLL_PTR爲空,以下圖:
image.png多線程

步驟二:

修改這個數據DATA爲BBB,此時的DB_TRX_ID爲2,DB_ROLL_PTR指向修改前的數據,以下圖:
image.pngspa

步驟三:

修改這個數據DATA爲CCC,此時的DB_TRX_ID爲3,DB_ROLL_PTR指向修改前的數據,以下圖:
image.png線程

ReadView機制

MySql是支持多線程的,因此當多個事務提交的時候,其中一個事務就會建立一個ReadView。
ReadView的結構以下:日誌

  • m_ids:當前未提交的事務
  • creator_trx_id:建立ReadView的事務
  • min_trx_id:m_ids中最小的事務id
  • max_trx_id:最大的事務id+1
    image.png
    咱們一樣用一個例子來講明這個機制。
    假設事務1插入了DATA爲AAA後,事務2和事務3對這條數據進行了查詢和修改。事務

    步驟1:

    事務2建立了ReadView。因此ReadView以下:get

  • m_ids爲2和3。
  • creator_trx_id爲2。
  • min_trx_id爲2。
  • max_trx_id爲4。
    image.png同步

    步驟2:

    事務2查詢了這條語句。
    事務2首先會判斷min_trx_id(2)和這條數據的DB_TRX_ID(1),此時2比1大,說明ReadView裏的事務都是在當前數據的事務後建立的。咱們固然能夠讀取以前的事務提交的數據。
    此時事務2直接讀取這條數據的DATA,AAA。it

    步驟3:

    事務3修改了這條語句,DATA改成BBB。
    事務3也會判斷min_trx_id(2)和這條數據的DB_TRX_ID(1),發現是以前事務提交 的數據,因此他就直接修改了此數據。
    image.pngclass

    步驟4:

    事務2繼續查詢了這條語句。
    事務2發現DB_TRX_ID(3)比min_trx_id(2)大,可是比max_trx_id(4)小,同時在m_ids(2,3)中,因此知道了這個修改數據的事務是跟本身在同一個ReadView中的,那他就不能讀取當前事務的數據,就根據DB_ROLL_PTR讀取上一個數據。
    因此又讀到了DB_TRX_ID(1)的DATA的值AAA。這就是可重複讀。

    步驟5:

    事務4修改了這條語句,DATA改成CCC。
    事務4會生成新的ReadView,而後發現DB_TRX_ID(3)是以前事務提交 的數據,因此他就直接修改了此數據。
    image.png

    步驟6:

    事務2繼續查詢這條語句,他對比DB_TRX_ID(4)和max_trx_id(4),發現這個數據被比本身後面的事務提交了,因此他也不能看到這個事務提交的數據,因而他就順着鏈表找到DB_TRX_ID(3),判斷同步驟6,最終仍是找到了DB_TRX_ID(1)的DATA爲AAA的數據。以上例子能夠看到,ReadView機制能夠保證能夠讀取到以前提交事務的數據,可是讀取不到一塊兒執行的事務以及以後的事務提交的數據。

相關文章
相關標籤/搜索