1. 程式人生 > >事務ACID的實現

事務ACID的實現

事務需要滿足ACID特性,那在資料庫中,它是如何實現的?我們接下來的內容將一一介紹。

1.隔離性

其實我們在《MySQL InnoDB引擎 MVCC併發控制》中談到了事務的隔離級別,但沒有談到怎樣實現隔離性。我們提到了要消除幻讀,一般的資料庫系統需要保證序列化的事務隔離級別,而MySQL InnoDB在可重複讀的事務隔離級別下消除了幻讀,功勞應該歸於Next-key Lock鎖。這個具體詳述在《MySQL InnoDB中的行鎖 Next-Key Lock消除幻讀》。那說了半天事務隔離級別,隔離性到底是如何實現的?其實在上面我們已經談到了,是鎖機制+MVCC。我們通過MVCC使得事務隔離級別達到了可重複讀,使用鎖機制消除了幻讀,實現了事務隔離

。需要注意的是,在使用分散式事務時,InnoDB儲存引擎的事務隔離級別必須設定為序列化。

2.永續性和原子性

通過資料庫的redo log重做日誌,來保證事務的永續性與原子性。

2.1 永續性

重做日誌由兩部分組成:重做日誌緩衝(記憶體)和重做日誌檔案(物理儲存)。當事務提交(commit)時,必須先將該事務的所有日誌寫入到重做日誌檔案進行持久化,待事務提交操作完成才算完成。redo log重做日誌基本上都是順序寫的。為了確保每次日誌都寫入重做日誌檔案,在每次將重做日誌快取寫入重做日誌檔案後,InnoDB儲存引擎都需要呼叫一次fsync(檔案同步)操作。當然MySQL提供一些引數來調整緩衝重新整理到檔案的策略,在這裡就不細講了。

2.2 原子性

在InnoDB儲存引擎中,重做日誌都是以512位元組進行儲存的,稱為重做日誌塊。若一個頁中產生的重做日誌數量大於512位元組,那麼需要分割為多個重做日誌塊進行儲存。由於重做日誌塊的大小與磁碟扇區大小一樣,都是512位元組,因此重做日誌的寫入可以保證事務的原子性。重做日誌塊大小為512位元組,但其中包含的有效儲存為492位元組,重做日誌檔案頭佔12位元組,日誌尾佔8位元組。

3. 一致性

通過資料庫的undo log撤銷日誌,來保證事務的一致性。
為了完成事務的回滾操作,在對資料庫進行修改時,InnoDB儲存引擎不但會產生redo log,還會產生一定量的undo logo。undo log是邏輯日誌,只是將資料庫邏輯地恢復到原來的樣子

,保證了事務的一致性(從一個狀態轉換為下一個一致性狀態)。

3.1 redu和undo的區別

redo恢復提交事務修改的頁操作,undo回滾行記錄到某個特定版本。
redo通常是物理日誌,記錄的是頁的物理修改操作。undo是邏輯日誌,根據每行記錄進行記錄。

3.2 undo誤解

通常對undo的誤解是undo用於將資料庫物理地恢復到執行語句或事務之前的樣子。事實上,NO!!!

舉個栗子:一個事務在修改當前一個頁中某幾條記錄,同時還有別的事務在對同一個頁中另幾條記錄進行修改。因此,不能將一個頁回滾到事務開始的樣子,因為這樣會影響其他事務正在進行的工作。所以,在上面我們說道undo log是邏輯日誌。

3.3 undo作用

除了回滾操作,undo的另一個作用是MVCC,在InnoDB儲存引擎中MVCC的實現是通過undo來完成。當用戶讀取一行記錄時,若該記錄已經被其他事務佔用,當前事務可以通過undo讀取之前的行版本資訊,以此實現非鎖定讀。
undo log會產生redo log,undo操作需要永續性保護。

參考:

  • 《MySQL技術內幕》