mysql事務怎麼實現的,什麼是兩階段提交

mysql事務怎麼實現的,什麼是兩階段提交

我們都知道使用mysql的事務,準確來說是innoDB引擎的事務,可以保證數據的一致性,原子性等。那麼爲什麼呢?

redo log

innoDB裏面用到了一個叫做redo log(重做日誌)的東西。

當你進行數據庫操作的時候,innoDB並不會直接操作磁盤數據,因爲這樣很慢很慢。它使用了wal的機制,所有的操作先記錄在redo log。等沒事幹了或者redo log滿了再把數據刷到磁盤裏面。這樣的話他刷盤的時候就是順序io,避免了使用隨機io。redo log的大小我們可以通過參數設置。

緩衝池

在innoDB裏面還有一個緩衝池,buffer_pool,這個緩衝池是在內存中的。爲啥有緩衝池,因爲磁盤的速度太慢了,如果每次都直接操作磁盤,那就完犢子了。就需要用到內存來緩衝一下,提升性能。

從innoDB裏面讀取數據的時候,實際上讀取的是緩衝池,只有當緩衝池中沒有記錄的時候,纔會讀取磁盤,並且將記錄放入緩衝池方便下次讀取。

緩衝池的大小可以通過innodb_buffer_pool_size參數來指定。

緩存池中基本有以下組件:

  • 索引頁
  • 數據頁
  • undo頁
  • 插入緩衝(insert buffer)
  • 自適應哈希索引
  • 鎖信息
  • 數據字典
  • redo log buffer

緩衝池既然是在內存中,有固定大小,就會有淘汰機制,緩衝池使用的是LRU機制,也就是最近最少使用的會被淘汰掉。

這裏面還有一個redo log buffer,這裏面存儲的就是上面說的redo log的信息了,會先寫入這個buffer,然後再刷入redo log裏面。有一個參數innodb_log_buffer_size來控制redo log buffer的大小。這個不用太大,因爲一般每秒都會把這裏面的刷新到redo log。

redo log buffer刷新到redo log的三種情況:

  • 每秒刷新
  • 事務提交時候刷新
  • 當redo log buffer剩餘空間少於一半的時候刷新

binlog

redo log是innoDB引擎的日誌,那mysql自己同樣有日誌,就是這個binlog日誌。binlog 裏面記載了mysql的所有變化,可以用來恢復數據庫,創建備庫,從庫等。可以查看我的mysql讀寫分離

那爲什麼有兩個日誌呢,這是因爲mysql最開始默認使用的是myisam引擎,myisam引擎沒有redo log,mysql就有自己的binlog。innoDB引擎是後來加入mysql的。所以他們各自有各自的日誌。

這兩個日誌有什麼區別呢?

  1. rodo log是innoDB引擎的,binlog 是mysql的,binlog所有引擎都可以使用。
  2. redo log記錄的是“再某個數據頁上修改了啥”,binlog記錄的是你的sql。
  3. redo log是固定大小,循環寫入的,binlog沒有大小限制,不斷追加。

事務

那一個事務怎麼執行的呢,比如更新一個登錄時間。

update user set login_time = ? where id = 1;
  • 走完了前面的連接器,分析器,優化器,執行器。執行器會去innoDB更新數據了。
  • 他會先取出這條數據,取出id = 1的數據,id是主鍵索引,和數據在一起。innoDB直接查找主鍵索引樹找到對應數據就返回了。當然,如果數據再緩衝池,那麼直接返回了。
  • 執行器拿到以後再修改登陸時間,然後再次調用innoDB引擎的接口。
  • innoDB把數據更新到內存中,同時更新redo log,把redo log標記成待提交狀態。
  • 執行器寫入binlog。
  • 執行器調用innoDB引擎的接口,innoDB把redo log標記成提交狀態。

這個時候整個更新事務完成。

爲什麼要這麼做呢?

因爲有兩個日誌的原因,所以兩個日誌都要寫入,要保證這兩個日誌的一致性。那麼如果不使用兩階段提交的方式,直接寫入redo log然後寫入binlog有什麼問題呢?

假設,寫完redo log,系統掛了。那麼重啓後innoDB引擎會根據redo log日誌來恢復數據庫。這時候數據庫裏面的數據是正確的。但是binlog丟失了啊。如果你有從庫,那麼從庫的數據就錯誤了。因爲從庫的數據是通過binlog同步的。

如果把這兩個步驟反過來呢,先寫入binlog 再寫入redo log呢?

那麼就會redo log丟失,數據庫實際上沒有更新。但是從庫通過binlog更新了。還是數據不一致。

所以需要兩階段提交來保證數據一致性。如果這時候寫完redo log後掛掉了,因爲redo log和binlog都沒有數據,所以會回滾事務。
如果binlog和redo log都寫入了,但是沒有提交,那麼重啓後會提交事務。這樣binlog和數據庫就都有數據了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章