MySQL & MariaDB效能最佳化 大牛的blog

mcxiaoracle發表於2023-10-16

在tydic 的做一個對應的方法分片的方法時對應的時候要比對MySQL 和

MariaDB效能最佳化:

在MySQL 5.5版本里,引入了MDL, 在事務過程中涉及到的所有表的MDL鎖,直到事務結束才釋放。這意味著上述序列的DROP TABLE 操作將被Session 1阻塞住直到其提交。


不過用過5.5的人都知道,MDL實在是個讓人討厭的東西,相信不少人肯定遇到過在使用mysqldump做邏輯備份時,由於需要執行FLUSH TABLES WITH READ LOCK (以下用FTWRL縮寫代替)來獲取全域性GLOBAL的MDL鎖,因此經常可以看到“wait for global read lock”之類的資訊。如果備庫存在大查詢,或者複製執行緒正在執行比較漫長的DDL,並且FTWRL被block住,那麼隨後的QUERY都會被block住,導致業務不可用引發故障。


為瞭解決這個問題,Facebook為MySQL增加新的介面替換掉FTWRL 只建立一個read view ,並返回與read view一致的binlog位點;另外Percona Server也實現了一種類似的辦法來繞過FTWRL,具體點選 以及 percona的部落格 ,不展開闡述。


MySQL 5.7 對MDL鎖的最佳化


在MySQL 5.7裡對MDL子系統做了更為徹底的最佳化。主要從以下幾點出發:

第一,儘管對MDL HASH進行了分割槽,但由於是以表名+庫名的方式作為key值進行分割槽,如果查詢或者DML都集中在同一張表上,就會hash到相同的分割槽,引起明顯的MDL HASH上的鎖競爭。


針對這一點,引入了LOCK-FREE的HASH來儲存MDL_lock,LF_HASH無鎖演演算法基於論文"Split-Ordered Lists: Lock-Free Extensible Hash Tables",實現還比較複雜。 注:實際上LF_HASH很早就被應用於Performance Schema,算是比較成熟的程式碼模組。由於引入了LF_HASH,MDL HASH分割槽特性自然直接被廢除了 。對應 WL#7305 , PATCH( )


第二,從廣泛使用的實際場景來看,DML/SELECT相比DDL等別MDL鎖型別,是更為普遍的,因此可以針對性的降低DML和SELECT操作的MDL開銷。

第二,從廣泛使用的實際場景來看,DML/SELECT相比DDL等別MDL鎖型別,是更為普遍的,因此可以針對性的降低DML和SELECT操作的MDL開銷。

為了實現對DML/SELECT的快速加鎖,使用了類似LOCK-WORD的加鎖方式,稱之為FAST-PATH,如果FAST-PATH加鎖失敗,則走SLOW-PATH來進行加鎖。

每個MDL鎖物件(MDL_lock)都維持了一個long long型別的狀態值來標示當前的加鎖狀態,變數名為MDL_lock::m_fast_path_state 舉個簡單的例子:(初始在sbtest1表上對應MDL_lock::m_fast_path_state值為0)

Session 1: BEGIN;
Session 1: SELECT * FROM sbtest1 WHERE id =1; //m_fast_path_state = 1048576, MDL ticket 不加MDL_lock::m_granted佇列
Session 2: BEGIN;
Session 2: SELECT * FROM sbtest1 WHERE id =2; //m_fast_path_state=1048576+1048576=2097152,同上,走FAST PATH
Session 3: ALTER TABLE sbtest1 ENGINE = INNODB; //DDL請求加的MDL_SHARED_UPGRADABLE型別鎖被視為unobtrusive lock,可以認為這個是比上述SQL的MDL鎖級別更高的鎖,並且不相容,因此被強制走slow path。而slow path是需要加MDL_lock::m_rwlock的寫鎖。m_fast_path_state = m_fast_path_state | MDL_lock::HAS_SLOW_PATH | MDL_lock::HAS_OBTRUSIVE
注:DDL還會獲得庫級別的意向排他MDL鎖或者表級別的共享可升級鎖,但為了表述方便,這裡直接忽略了,只考慮涉及的同一個MDL_lock鎖物件。
Session 4: SELECT * FROM sbtest1 WHERE id =3; // 檢查m_fast_path_state &HAS_OBTRUSIVE,如果DDL還沒跑完,就會走slow path。

從上面的描述可以看出,MDL子系統顯式的對鎖型別進行了區分(OBTRUSIVE or UNOBTRUSIVE),儲存在陣列矩陣m_unobtrusive_lock_increment。 因此對於相容型別的MDL鎖型別,例如DML/SELECT,加鎖操作幾乎沒有任何讀寫鎖或MUTEX開銷。對應 WL#7304WL#7306 , PATCH( , )( )


參考資料:

https://www.cnblogs.com/stevetang/p/4829617.html





















來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69949806/viewspace-2989224/,如需轉載,請註明出處,否則將追究法律責任。

相關文章