MySQL事務提交過程(一)

來源:互聯網
上載者:User

標籤:

MySQL作為一種關係型資料庫,已被廣泛應用到互連網中的諸多項目中。今天我們來討論下事務的提交過程。

                                                       MySQL體繫結構

 

由於mysql外掛程式式儲存架構,導致開啟binlog後,事務提交實質是二階段提交,通過兩階段交易認可,來保證儲存引擎和二進位日誌的一致。

本文僅討論binlog未打卡狀態下的提交流程,後續會討論開啟binlog選項後的提交邏輯。

   

測試環境

OS:WIN7

ENGINE:

bin-log:off

DB:

   

測試條件

set autocommit=0;
-- ------------------------------ Table structure for `user`-- ----------------------------DROP TABLE IF EXISTS `user`;CREATE TABLE `user` (`id` int(20) NOT NULL,`account` varchar(20) NOT NULL,`name` varchar(20) NOT NULL,PRIMARY KEY (`id`),KEY `id` (`id`) USING BTREE,KEY `name` (`name`) USING BTREE) ENGINE=InnoDB DEFAULT CHARSET=utf8;

   

測試語句

insert into user values(1, ‘sanzhang‘, ‘張三‘);
commit;

   

一般常用的DML(insert、update、delete)語句和DCL(commit、rollback)語句,均是使用MySQL提供的公用介面mysql_execute_command,來執行相應的SQL語句。我們來分析下mysql_execute_command介面執行的流程:

mysql_execute_command{   switch (command)   {       case SQLCOM_INSERT:                mysql_insert();                break;       case SQLCOM_UPDATE:                mysql_update();                break;       case SQLCOM_DELETE:                mysql_delete();                break;       ......   }   if thd->is_error()  //語句執行錯誤     trans_rollback_stmt(thd);  else    trans_commit_stmt(thd);}

   

從上述流程中,可以看到執行任何語句,最後都會執行trans_rollback_stmt或者trans_commit_stmt,這兩個分別是語句復原和語句提交。

語句提交,對於非自動模式下,主要有兩個作用:

1、釋放autoinc鎖,這個鎖主要用來處理多個事務互斥的擷取自增序列。因此,無論最後執行的是語句提交還是語句復原,該資源都是需要立馬釋放掉的。

2、標識語句在事務中的位置,方便語句級復原。執行commit後,可以進入commit流程。

現在看下具體的事務提交流程:

mysql_execute_commandtrans_commit_stmtha_commit_trans(thd, FALSE);{    TC_LOG_DUMMY:ha_commit_low        ha_commit_low()               innobase_commit            {                //擷取innodb層對應的事務結構                trx = check_trx_exists(thd);                if(單個語句,且非自動認可)                {                     //釋放自增列佔用的autoinc鎖資源                     lock_unlock_table_autoinc(trx);                     //標識sql語句在事務中的位置,方便語句級復原                     trx_mark_sql_stat_end(trx);                }                else 事務提交                {                     innobase_commit_low()                     {                          trx_commit_for_mysql();                            <span style="color: #ff0000;">trx_commit</span>(trx);                      }//確定事務對應的redo日誌是否落盤【根據flush_log_at_trx_commit參數,確定redo日誌落盤方式】                    trx_commit_complete_for_mysql(trx);trx_flush_log_if_needed_low(trx->commit_lsn);log_write_up_to(lsn);                }            }}
trx_commit    trx_commit_low        {            trx_write_serialisation_history            {                trx_undo_update_cleanup //供purge線程處理,清理復原頁            }            trx_commit_in_memory            {                lock_trx_release_locks //釋放鎖資源                trx_flush_log_if_needed(lsn) //刷日誌                trx_roll_savepoints_free //釋放savepoints            }        }

 

MySQL是通過WAL方式,來保證資料庫事務的一致性和持久性,即ACID特性中的C(consistent)和D(durability)。

WAL(Write-Ahead Logging)是一種實現交易記錄的標準方法,具體而言就是:

1、修改記錄前,一定要先寫日誌;

2、事務提交過程中,一定要保證日誌先落盤,才能算事務提交完成。

通過WAL方式,在保證事務特性的情況下,可以提高資料庫的效能。

   

從上述流程可以看出,提交過程中,主要做了4件事情,

1、清理undo段資訊,對於innodb儲存引擎的更新操作來說,undo段需要purge,這裡的purge主要職能是,真正刪除物理記錄。在執行delete或update操作時,實際舊記錄沒有真正刪除,只是在記錄上打了一個標記,而是在事務提交後,purge線程真正刪除,釋放物理頁空間。因此,提交過程中會將undo資訊加入purge列表,供purge線程處理。

2、釋放鎖資源,mysql通過鎖互斥機制保證不同事務不同時操作一條記錄,事務執行後才會真正釋放所有鎖資源,並喚醒等待其鎖資源的其他事務;

3、刷redo日誌,前面我們說到,mysql實現事務一致性和持久性的機制。通過redo日誌落盤操作,保證了即使修改的資料頁沒有即使更新到磁碟,只要日誌是完成了,就能保證資料庫的完整性和一致性;

4、清理儲存點列表,每個語句實際都會有一個savepoint(儲存點),儲存點作用是為了可以復原到事務的任何一個語句執行前的狀態,由於事務都已經提交了,所以儲存點列表可以被清理了。

   

關於mysql的鎖機制,purge原理,redo日誌,undo段等內容,其實都是資料庫的核心內容。

MySQL 本身不提供事務支援,而是開放了儲存引擎介面,由具體的儲存引擎來實現,具體來說支援 MySQL 事務的儲存引擎就是 InnoDB。

儲存引擎實現事務的通用方式是基於 redo log 和 undo log。

簡單來說,redo log 記錄事務修改後的資料, undo log 記錄事務前的未經處理資料。

所以當一個事務執行時實際發生過程簡化描述如下:

  1. 先記錄 undo/redo log,確保日誌刷到磁碟上持久儲存。
  2. 更新資料記錄,快取作業並非同步刷盤。
  3. 提交事務,在 redo log 中寫入 commit 記錄。

在 MySQL 執行事務過程中如果因故障中斷,可以通過 redo log 來重做事務或通過 undo log 來復原,確保了資料的一致性。

這些都是由事務性儲存引擎來完成的,但 binlog 不在事務儲存引擎範圍內,而是由 MySQL Server 來記錄的。

那麼就必須保證 binlog 資料和 redo log 之間的一致性,所以開啟了 binlog 後實際的事務執行就多了一步,如下:

  1. 先記錄 undo/redo log,確保日誌刷到磁碟上持久儲存。
  2. 更新資料記錄,快取作業並非同步刷盤。
  3. 將交易記錄持久化到 binlog。
  4. 提交事務,在 redo log 中寫入提交記錄。

這樣的話,只要 binlog 沒寫成功,整個事務是需要復原的,而 binlog 寫成功後即使 MySQL Crash 了都可以恢複事務並完成提交。

要做到這點,就需要把 binlog 和事務關聯起來,而只有保證了 binlog 和交易資料的一致性,才能保證主從資料的一致性。

所以 binlog 的寫入過程不得不嵌入到純粹的事務儲存引擎執行過程中,並以內部分散式交易(xa 事務)的方式完成兩階段交易認可。

   

參考

    1、《高效能MySQL》   

MySQL事務提交過程(一)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.