MySQL 5.7: Innodb 事務子系統優化

jopen 10年前發布 | 15K 次閱讀 MySQL 數據庫服務器

之前寫了篇博客介紹了Percona Server對Read View的優化,順帶簡單提到了MySQL5.7的事務子系統優化,詳細見http://mysqllover.com/?p=834 。 另外一篇博客http://mysqllover.com/?p=1087  也有所涉及。

本文總體介紹了幾個和事務子系統相關的worklog以及其代碼實現。這部分代碼值得細讀,因為他們是5.7 Innodb比較核心的改動,極大的提升了只讀場景下的性能。

WL#6047

這個worklog包含幾點變化:

第一,無需顯示的開啟只讀事務,所有的事務開始默認為只讀事務,當遇到讀寫SQL時,自動加入讀寫列表。

第二,只讀事務不為其分配事務ID,因此如果SHOW ENGINE INNODB STATUS時看到大量事務的ID為0時,不要覺得奇怪。

該改進帶來的最大的好處是你無需修改你的業務SQL。其實這才是用戶能接受的特性,如果沒有量級別的提升,誰會愿意去改代碼呢?

我們以一個典型的例子來開啟這個話題,首先準備一個簡單的表。隔離級別為READ-COMMIT

CREATE TABLE t1 (a INT PRIMARY KEY, b INT);

INSERT INTO t1 VALUES (1,RAND()*100),(2,RAND()*100);

BEGIN;

以BEGIN顯式開啟一個事務;

b) SELECT * FROM t1;

分配一個事務句柄:

ha_innobase::open

ha_innobase::info_low

update_thd

check_trx_exists

innobase_trx_allocate

trx_allocate_for_mysql

</blockquote>

新分配的事務句柄會加入到trx_sys->mysql_trx_list,并重復使用。

開始一個只讀事務,開啟的事務,不分配事務ID, 不分配回滾段

row_search_mvcc->trx_start_if_not_started->trx_start_low

Assign Read View

row_search_mvcc

trx_assign_read_view

MVCC::view_open

</blockquote>

分配的read view會拷貝當前的活躍事務ID,設置最高和最低可見事務ID,然后加入到活躍事務的read view鏈表上(MVCC::m_views)

c) UPDATE t1 SET b=b+1 WHERE a=2;

row_search_mvcc

lock_table

trx_set_rw_mode

</blockquote>

將事務轉換成讀寫事務模式,分配回滾段,分配事務ID。加入讀寫事務鏈表(trx_sys->rw_trx_ids, trx_sys->rw_trx_set, trx_sys->rw_trx_list)。

d) COMMIT; 事務提交

代碼:

http://bazaar.launchpad.net/~mysql/mysql-server/5.7/revision/5209

WL#6578

在該worklog種優化了read view的創建,對MVCC控制視圖部分的代碼進行了重構。

具體包括以下幾個方面:

在之前版本中,read view的創建的復雜度為O(N),因為需要掃描讀寫事務鏈表;

現在創建一個read view 需要以下幾步:

Step 1:

                view->prepare(trx->id);

拷貝事務ID(不包含自己的事務ID),相當于做一個當前活躍讀寫事務的快照存放在視圖中,直接使用memcpy的方式 (copy_trx_ids(trx_sys->rw_trx_ids)),這一點和percona的優化是一樣的。

設置m_low_limit_no ,m_low_limit_id

Step 2:

                view->complete();

設置視圖的m_up_limit_id,表示所有小于這個值的修改都可見

Step 3:

                UT_LIST_ADD_FIRST(m_views, view);

將視圖加入到活躍視圖鏈表中。

b)  在之前版本中是在持有trx_sys mutex時創建的read view。

為了降低分配/釋放read view的開銷,維護了兩個read view鏈表,一個用于放當前活躍的視圖鏈表,一個用于放空閑的、可分配的視圖鏈表。

當系統啟動時,會初始化一定數量的read view放到空閑鏈表上。

Percona實現了類似的方案,不同的是Percona的read view在事務完成后不是放到空閑鏈表,而是下次繼續重用(但從活躍鏈表移除,不管是否是讀寫事務)

c) 對于autocommit的只讀事務,即時當前沒有活躍事務,也可能因為創建read view ,而大量別的線程在釋放read view,導致trx_sys mutex沖突。

針對該問題,實際上我已經在博文http://mysqllover.com /?p=1087中描述過了,對于自動提交的查詢,在關閉read view時是不從視圖鏈表上移除的,在再次開啟事務重用該read view時,如果這期間沒有讀寫事務,都無需重新初始化read view,直接使用即可。 因此如果一臺實例上的都是自動提交的只讀事務,完全可以避免trx_sys mutex的開銷。

d) 需要持有trx_sys mutex來遍歷rw_trx_list,以判斷更改是否可見,或者根據事務id獲取事務對象trx_t

由于已經保存了事務ID的快照,因此直接根據二分查找查找有序數組即可,無需遍歷讀寫事務鏈表

參考函數ReadView::changes_visible

trx_sys_t新增成員rw_trx_set,用于維護從trx_id到trx_t的映射。這樣可以根據事務ID快速找到對應的事務對象而無需掃描事務鏈表。參考函數trx_get_rw_trx_by_id

主要更改:

http://bazaar.launchpad.net/~mysql/mysql-server/5.7/revision/6203

http://bazaar.launchpad.net/~mysql/mysql-server/5.7/revision/6204

http://bazaar.launchpad.net/~mysql/mysql-server/5.7/revision/6205

http://bazaar.launchpad.net/~mysql/mysql-server/5.7/revision/6224

http://bazaar.launchpad.net/~mysql/mysql-server/5.7/revision/6236

在完成上述修改后,無需再維持ro_trx_list了,因為所有事務默認都被當做只讀事務,這個鏈表開銷完全可以忽略掉的。

http://bazaar.launchpad.net/~mysql/mysql-server/5.7/revision/6788

WL#6899

該worklog主要實現了隱式鎖向現式鎖轉換的一個優化點。在獲取活躍事務對象時,無需持有lock_sys mutex鎖。

更詳細的,參考我之前寫的這篇博客:http://mysqllover.com/?p=1035

WL#6906

在連續內存中預分配事務對象,保持內存的連續性有利于編譯器或者CPU做出某些優化,例如內存預取之類的(不是很了解這一塊,不展開敘述)

為了實現事務對象內存分配,回收等,在底層分裝了一些pool類,事務對象實際上被管理在一個池結構中。

后面我再單獨寫一篇博客來介紹新加的這些底層結構。

在啟動時,初始化trx_pools (trx_pool_init),初始化時分配4M內存,在shutdown時釋放(trx_pool_close())

為了管理事務對象池,設計了三個類:TrxFactory,TrxPoolLock,TrxPoolManagerLock

獲取事務對象:trx_create_low —-> trx_pools->get()

釋放事務對象:trx_free —->  trx_pools->free(trx)

http://dev.mysql.com/worklog/task/?id=6906

相關代碼:

http://bazaar.launchpad.net/~mysql/mysql-server/5.7/revision/5744

http://bazaar.launchpad.net/~mysql/mysql-server/5.7/revision/5750

http://bazaar.launchpad.net/~mysql/mysql-server/5.7/revision/5753

http://bazaar.launchpad.net/~mysql/mysql-server/5.7/revision/5756

http://bazaar.launchpad.net/~mysql/mysql-server/5.7/revision/5786

原創文章,轉載請注明: 轉載自Simple Life

本文鏈接地址: MySQL 5.7: Innodb 事務子系統優化

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!