原文地址:mysqlserverteam.com/contention-…
原文做者: Sunny Bains, Jiamin Huang (University of Michigan)
譯者:沈剛mysql
目前大多數的數據庫系統都是經過鎖的方式來控制併發的狀況。可是對於不少數據庫廠商來講,都會有一個問題:git
當有多個事務同時須要獲取同一把鎖,那麼哪一個事務應該最早得到這把鎖?github
包括以前版本的MySQL在內,幾乎全部的數據庫都是經過FIFO機制來解決這個問題。簡單來講,FIFO機制就是將鎖分配給最早請求該鎖的事務(即該事務在等待隊列的最前面,除非它們與當前鎖賦予的鎖不兼容)。由於這種機制是實現起來簡單,因此不少的數據庫廠商都是經過FIFO的策略進行事務調度,沒有考慮其餘的調度策略。算法
最近一個密歇根大學的研究組織提出,這個問題背後隱藏着巨大的性能提高空間。Mozafari教授和他的學生證實了不一樣的鎖分配策略以及事務調度策略對於數據庫性能有着很大的影響。他們提出了一種稱之爲Contention-Aware Transaction Scheduling(CATS)的算法,使用這種算法進行事務調度相較於以前的FIFO策略,顯著地減小了數據庫延遲,提升了吞吐量。sql
Oracle MySQL官方團隊和Mozafari教授以及他的學生們緊密合做,使得MySQL是第一個採用這種新技術的數據庫。在MySQL 8.0.3版本以後,CATS策略做爲InnoDB的默認調度算法,也就是說MySQL的使用者能夠感受到顯著的性能提高,尤爲是在持續高壓力負載的狀況下。數據庫
CATS算法是基於很簡單的一個觀點:不是全部的事務都是平等的,不是全部的對象都是平等的。當一個事務已經持有了多個對象的鎖,當該事務請求一個新的鎖的時候,該事務應該被優先分配。從另外一個方面講,解鎖這樣的事務有助於解鎖更多的事務。由於該事務優先被分配鎖能更快的結束事務,釋放另外已經獲取到的對象的鎖。經過這種方式可使數據庫得到更高的吞吐和更低的延遲。併發
有一個比喻的例子:若是有一個出租車司機和一個公交車司機都在等咖啡,那麼先給公交車司機作咖啡(即便公交車司機比出租車司機遲來)可能會讓更多的人儘早到達他們的目的地。由於公交車上的乘客比出租車上的乘客多。這看起來彷佛對出租車司機不公平,可是這種策略可使得整個系統運行的更快,這對於系統內的每一個人都是有利的。sqlserver
固然,咱們如今是在解決鎖的問題而不是交通司機的問題。讓咱們經過一個簡單的例子來闡述一下CATS機制在數據庫中是如何工做的。咱們知道在不一樣的事務隔離級別下,事務在讀取或者更新數據的時候,須要先獲取對應數據的鎖。當一個事務所須要的鎖已經被其餘事務所持有了,那麼這個事務會一直等待直到其餘事務釋放這個鎖。當事務已經持有一部分對象鎖的時候,可能會在獲取其餘對象的鎖的時候一直被阻塞住,這個時候就須要死鎖檢測機制來檢測當前數據庫中沒有鎖等待循環,防止死鎖。來看下面這張圖: 性能
Transaction contention 在這種場景下,FIFO策略很簡單,只須要考慮那個事務先請求O1對象的鎖。可是CATS算法會更加智能地處理這個狀況:CATS算法會計算每一個事務直接阻塞和間接阻塞的事務數量,而後將O1對象的鎖分配給阻塞了更多事務的事務。在這個場景下,t1事務阻塞了4個事務,t2事務阻塞了3個事務。因此根據CATS算法會將O1對象的鎖分配給t1事務。這樣能夠將更多的事務釋放出來,這樣有利於提升系統總體的性能。測試
對於共享鎖(S鎖),CATS算法會盡量多的分配共享鎖。在這方面FIFO和CATS算法有不一樣的地方。FIFO按照隊列的前後順序分配共享鎖,當遇到分配的對象上已經有排他鎖(X鎖)了,則中止分配。而在CATS中,按照事務阻塞的事務數進行倒序排序,而後按照這個順序進行鎖分配。
Oracle的Dimitri Kravtchuk經過Sysbench 的OLTP腳本測試這種新的算法。經過結果顯示,在併發狀況下,CATS算法比FIFO算法在TPS,平均延遲,95%延遲等指標方面都有顯著的性能提高。有趣的是,即便在沒有併發的狀況下,CATS算法的性能和FIFO算法性能是同樣的。那是由於在沒有併發的時候,沒有事務須要進行調度,因此也就沒有性能的差別。換而言之,使用CATS算法替換FIFO算法,沒有任何損失,反而在數據庫繁忙的時候,有很大的性能提高。
CATS vs. FIFO in TPS, mean latency and 95th percentile (up to 5.05x improvement)
MySQL是全球第一個使用這種最早進的CATS事務調度算法的數據庫。這個算法解決了數據庫在遇到高壓力狀況下性能急劇降低的問題,這個也是MySQL 8.0主要想要達到的目標。 CATS算法是針對當事務併發超過32的狀況,這個數值沒有參數配置,是經過經驗設置的。
博客地址:win-man.github.io/
公衆號:歡迎關注