回顧 MySQL / InnoDB 的改善曆史。你能很容易發現。在MySQL 5.6穩定版本中(zhōng)從來沒有在read-only 這麽快的提速,它很容易搞懂,以及在read-only(RO)有着良好的擴張性。也很期待它在read+write(RW)上達到一(yī)個較高水平。(特别是在讀取數據是數據庫主要工(gōng)作的時候)
然而。我(wǒ)(wǒ)們對于RO在 MySQL 5.6的表現也十分(fēn)的高興,在5.7這個版本中(zhōng),主要工(gōng)作集中(zhōng)在 read+write (RW)上, 因爲在大(dà)數據的處理上還沒能達到我(wǒ)(wǒ)們的期望。但是RW依賴RO下(xià)。能夠再次提高速度。 InnoDB 團隊通過不斷的改進,強烈的推進優化着5.7這個版本的每秒的性能。
下(xià)面就按順序爲大(dà)家講解
事實上,在MySQL中(zhōng)隻讀工(gōng)作量控制内部鏈接的方式有以下(xià)兩種:
用單個表:MDL,trx_sys和lock_sys(InnoDB)
多表:trx_sys和lock_sys(主要是InnoDB)
任何很快的單表範圍測試的工(gōng)作量主要由于MDL鏈接導緻鎖住。而多表将會由于InnoDB内部構件限制(不同的表将由不同的MDL鎖保護,所以這種情況下(xià)MDL中(zhōng)的鏈接瓶頸将會降低)。但是同樣,也要看工(gōng)作量的大(dà)小(xiǎo)--一(yī)個比一(yī)般多的隻讀工(gōng)作測量将會在MySQL5.6中(zhōng)表現的會更好(如Sysbench OLTP_RO),同時在工(gōng)作量少而快的查詢(如Sysbench Point-Selects(用外(wài)鍵去(qù)取一(yī)個記錄))将會使所有鏈接變得困難,而且隻能在16核-HT中(zhōng)測量,而在32核中(zhōng)表現很差..但是任何如Point-Select測試的工(gōng)作量将在所有MySQL内部構件一(yī)起工(gōng)作是會讓你看到可能達到最大(dà)的性能(開(kāi)始用SQL解析器,終止與取行值)..在你給定的MySQL版本和給定的HW配置下(xià),這也可能達到最大(dà)SQL 查詢/每秒(QPS)率。
在Mysql5.6上我(wǒ)(wǒ)們獲得的最佳結果是25萬個查詢每秒,這也是那段時間Mysql/InnoDb上使用SQL語句查詢得到的最好的結果了。
當然,隻有在使用‘隻讀事務’功能才能達到這麽高速度(Mysql5.6上的新功能);另外(wài),需要使用AUTOCOMMIT=1,否則CPU就會被輕易地浪費(fèi)在啓動事務、提交事務上,你會實際上損失系統的整體(tǐ)性能。
因此,在Mysql5.7上介紹的第一(yī)個改進是‘隻讀事務的自動發現’(實際上每個InnoDb事務都被認爲是隻讀的直到有一(yī)個DML聲明在此之外(wài))功能---,這很大(dà)程度上簡化了隻讀事務功能,節省了用戶和開(kāi)發者的時間,他們不用再去(qù)管理是否采用隻讀事務功能。但是,使用這個功能你仍然不能達到Mysql潛在的最佳每秒查詢率,因爲CPU時間還是浪費(fèi)在事務的開(kāi)啓、結束狀态處理過程當中(zhōng)。
同時,Percona用不同的的方案來解決“事務列表”管理(TRX-列表)及在InnoDB中(zhōng)trx_sys互斥鏈接慢(màn)的問題。Percona的解決方案在用事務處理Point-Selects高負載時能表現良好,但MySQL5.7表現一(yī)般(但我(wǒ)(wǒ)不會公布5.7的結果,因爲它的代碼不公開(kāi))...所以,至少我(wǒ)(wǒ)現在可以做一(yī)些比較:
觀察結果:
在MySQL5.6,Percona 5.5和MySQL5.7中(zhōng)的8個表中(zhōng)用同樣的Roint-Select-TRX隻讀測試(用事務)(2013.5月的結果)
同時你也可以看到,在同樣的16核-HT配置下(xià)我(wǒ)(wǒ)們離(lí)峰值25萬/s的結果還很遠。
MySQL5.6在trx_sys互斥訪問中(zhōng)延長了鏈接時間,而且自從64個用戶後每秒的請求數将減少。
Percona5.5能維持很長的時間的負載,每秒請求在512個用戶時才開(kāi)始減少
當MySQL5.7已經保持一(yī)段時間時,每秒請求依然沒有減少(對于更多用戶并發的情況你在這幅圖裏是看不到的)...
然而,很明顯,如果用MySQL想要得到最大(dà)的潛在每秒查詢速率,事務應當避免。
讓我(wǒ)(wǒ)們來看一(yī)看這是2013年5月我(wǒ)(wǒ)們的每秒最大(dà)查詢速率。
在同一(yī)點八張表進行測試,但是沒有使用MySQL5.6的事物(wù):
觀察:
上面的測試是保持MySQL5.6始終執行在16核上,然後是16芯-HT,32核,32芯-HT.
正如你所看到的,最大(dà)的每秒查詢速率比預期的還要大(dà) -—— 在MySQL上是每秒27.5萬
最大(dà)的結果已經達到16芯-HT.
然而在32核上的結果并沒有16芯-HT上的好(由于競争中(zhōng)斷,在相同内核中(zhōng),具有2CPU線程的配置能夠更好的管理線程競争——所以真正的并發性仍保存在16線程,而不是32核上)
而在MySQL5.7上做同樣的測試卻看起來大(dà)有不同,因爲在5.7中(zhōng)lock_sys互斥鏈接的時間段已經很低了,同時trx_sys互斥相關代碼也得到第一(yī)次變化的情形:
觀察結果:
首先你可以看到5.7在同樣的16核-HT配置下(xià)的性能已經比5.6的要好
之後,在32核配置下(xià)沒有明顯的增強!
在32核-HT配置下(xià)達到了35萬/秒的最大(dà)請求!
從上面特殊(具有攻擊性)隻讀負載測試的情況下(xià)可以容易看出我(wǒ)(wǒ)們在32核中(zhōng)得到的結果要比16的好,同時我(wǒ)(wǒ)們還沒有啓動超線程(在32核-HT)...牛吧!;-)
從另一(yī)方面來講,仍然有改進的空間這點還是很清晰的。有關trx_sys的争用仍然在持續。我(wǒ)(wǒ)們沒有充分(fēn)的使用CPU的能力來做有用的工(gōng)作(仍然有許多CPU周期用在鎖的輪轉)...不過現在的結果比以前好多了,并且比5.6好很多,因此沒有理由繼續挖掘來提高這方面的性能,我(wǒ)(wǒ)們主要集中(zhōng)在我(wǒ)(wǒ)們曾經花費(fèi)了巨大(dà)的空間的讀寫負載的性能提高上。
到了5月底,也就是我(wǒ)(wǒ)們的性能會議期間,Sunny給try_sys互斥争用增加了幾個新的更改,從那以後最大(dà)的每秒可進行的查詢(QPS)可達到375K!這是不是對5.7進行了足夠的性能提高,對嗎(ma)?;-)
同時,我(wǒ)(wǒ)們繼續與建議用其他方式管理TRX列表的Percona團隊交換了意見,他們的方案看起來非常有趣,不過在5.5上,這樣的代碼卻不能展示出更高的每秒可進行的查詢數(QPS),而且在5.6上的這樣代碼(曾經測試過Percona Server 5.6)最大(dà)的每秒可進行的查詢數(QPS)也不會比在MySQL 5.6上大(dà)。然而,讨論涉及到一(yī)個有趣的觀點:如果同時有一(yī)些讀寫負載在運行的話(huà),它對隻讀性能有什麽影響呢?...而且,即使在同樣的測試條件下(xià)MySQL 5.7代碼仍然運行的要好一(yī)些,效果是非常明顯的(你可以在這兒查看我(wǒ)(wǒ)的分(fēn)析,然而,再次說明一(yī)下(xià),這段時間内我(wǒ)(wǒ)不能展示5.7上的結果,因爲它的代碼還沒有對大(dà)衆公布-也許會在以後的一(yī)篇文章中(zhōng)給出)..
由于這兒同時對任何純粹的讀寫負載也有影響,因此有足夠的動機以Sunnys很長時間所期待的那樣重新寫整個TRX列表相關的代碼,然而,這種經曆簡直讓人癡迷!
;-)) 日複一(yī)日,我(wǒ)(wǒ)們很高興的看到我(wǒ)(wǒ)們的每秒可進行的查詢圖逐漸變高,直到在同一(yī)個32核的超線程服務器上達到了每秒可進行的查詢440K!
5.7開(kāi)發裏程碑發布2上進行的Select 8個表所得到的結果數:
不需要說明..;-))
然而,有一(yī)個小(xiǎo)小(xiǎo)的令人奇怪的地方-我(wǒ)(wǒ)們試圖與Sunny通過不同的工(gōng)具分(fēn)析所有瓶頸和代碼更改所帶來的影響。而且在某些測試裏,令我(wǒ)(wǒ)吃驚的是Sunny觀察到比我(wǒ)(wǒ)更高的每秒可進行的查詢數..這個“奇異之處”與下(xià)面因素相關:
在高負載下(xià),現在的5.7代碼都運行在接近硬件極限(主要是CPU)的位置,因此每條指令都非常重要!
如果使用的Unix套接字或者IP端口,那麽區分(fēn)就會非常明顯!
Sysbench自身使用了30%的CPU時間,不過同樣的測試負載使用的是(具有更短的代碼路徑的)老版本的Sysbench的話(huà),它将隻使用20%CPU,剩餘的10%用在MySQL服務器上。
因此,同樣測試負載的情況下(xià),使用Unix套接字而不是IP 端口,并且使用Sysbench-0.4.8替代Sysbench-0.4.13的話(huà),我(wǒ)(wǒ)們将得到每秒可進行的查詢數超過500K!-很容易,不是嗎(ma)?;-))
讓我(wǒ)(wǒ)們來比較“之前”和“之後”的差異
觀察結果:
通過Sysbench降低了CPU的使用率。
在MySQL服務器上具有更高的CPU可用性。
我(wǒ)(wǒ)們實現了50萬每秒查詢。
還有什麽呢?
我(wǒ)(wǒ)可能隻提到:kudos Sunny和整個MySQL的開(kāi)發團隊;
讓我(wǒ)(wǒ)們看一(yī)下(xià)現在選擇8張表工(gōng)作負載的情況下(xià)的最大(dà)每秒查詢。
MySQL-5.7.2 (DMR2)
MySQL-5.6.14
MySQL-5.5.33
Percona Server 5.6.13-rc60.5
Percona Server 5.5.33-rel31.1
MariaDB-10.0.4
MariaDB-5.5.32
每個引擎都在以下(xià)配置下(xià)進行測試:
CPU taskset: 8核-HT,16核,16核-HT,32核,32核-HT
并發會話(huà)數:8,16,32 ... 1024
InnoDB自旋等待延時:6,96
最好的結果是來自任意兩個特定的組合間的比較。通過對數據庫引擎的比較,我(wǒ)(wǒ)得到了下(xià)面的一(yī)個圖表,這個圖表我(wǒ)(wǒ)在以前的文章中(zhōng)已經提到過了。
下(xià)面是一(yī)些評論:
對Mysql5.7的巨大(dà)差距結果不需要做過多的評論,因爲這是很明顯的。
那麽,有趣的是基于MySQL5.5的代碼庫引擎沒有任何的接近MySQL5.6的結果。
這已經證實了在使用MySQL5.6的代碼庫引擎之後,Percona Server達到了MySQL5.6的水平,然而MariaDB-10仍然還在探索的路上。
因此,毫無疑問,MySQL5.6是代碼的基石!
MySQL5.7是在MySQL5.6基礎上的再一(yī)次優化擴展。
具有什麽樣的擴展性呢?
答案是簡單的:MySQL5.7是唯一(yī)在此基礎上進行擴展的。
如果使用ip端口和一(yī)個重量級的Sysbench-0.4.13,會得到如下(xià)的結果:
QPS隻是稍微的略低一(yī)點,但是總體(tǐ)的趨勢是完全一(yī)樣的。
可擴展性也是非常的相似:
更多的結果将會出來,敬請期待;
注意:對一(yī)個單表綁定過多的工(gōng)作負載是不好的:
減少InnoDB間的争論使得其他的争論更加的明顯。
當負載是綁定在一(yī)張單表上時候,MDL的争論将變得更加主導。
這是預期希望的,我(wǒ)(wǒ)們在下(xià)一(yī)個DMRS上将保持不變。
還有很多挑戰擺在我(wǒ)(wǒ)們面前;-)
作爲參考,我(wǒ)(wǒ)上述測試的硬件配置信息如下(xià):
Server : 32cores-HT (bi-thread) Intel 2300Mhz, 128GB RAM
OS : Oracle Linux 6.2
FS : 啓用"noatime,nodiratime,nobarrier"挂載的EXT4
my.conf:
max_connections=4000 key_buffer_size=200M low_priority_updates=1 table_open_cache = 8000 back_log=1500 query_cache_type=0 table_open_cache_instances=16 # files innodb_file_per_table innodb_log_file_size=1024M innodb_log_files_in_group = 3 innodb_open_files=4000 # buffers innodb_buffer_pool_size=32000M innodb_buffer_pool_instances=32 innodb_additional_mem_pool_size=20M innodb_log_buffer_size=64M join_buffer_size=32K sort_buffer_size=32K # innodb innodb_checksums=0 innodb_doublewrite=0 innodb_support_xa=0 innodb_thread_concurrency=0 innodb_flush_log_at_trx_commit=2 innodb_max_dirty_pages_pct=50 innodb_use_native_aio=1 innodb_stats_persistent = 1 innodb_spin_wait_delay= 6 / 96 # perf special innodb_adaptive_flushing = 1 innodb_flush_neighbors = 0 innodb_read_io_threads = 4 innodb_write_io_threads = 4 innodb_io_capacity = 4000 innodb_purge_threads=1 innodb_adaptive_hash_index=0 # monitoring innodb_monitor_enable = '%' performance_schema=OFF
如果你需要的話(huà),Linux Sysbench的二進制版本在這裏:
Sysbench-0.4.13-lux86
Sysbench-0.4.8-lux86
使用UNIX socket來運行Point-Selects測試的Sysbench命令如下(xià)(在parallel中(zhōng)啓動8個進程):
LD_PRELOAD=/usr/lib64/libjemalloc.so /BMK/sysbench-0.4.8 --num-threads=$1 --test=oltp --oltp-table-size=10000000 \ --oltp-dist-type=uniform --oltp-table-name=sbtest_10M_$n \ --max-requests=0 --max-time=$2 --mysql-socket=/SSD_raid0/mysql.sock \ --mysql-user=dim --mysql-password=dim --mysql-db=sysbench \ --mysql-table-engine=INNODB --db-driver=mysql \ --oltp-point-selects=1 --oltp-simple-ranges=0 --oltp-sum-ranges=0 \ --oltp-order-ranges=0 --oltp-distinct-ranges=0 --oltp-skip-trx=on \ --oltp-read-only=on run > /tmp/test_$n.log &
使用IP端口來運行Point-Selects測試的Sysbench命令如下(xià)(在parallel中(zhōng)啓動8個進程):
LD_PRELOAD=/usr/lib64/libjemalloc.so /BMK/sysbench-0.4.13 --num-threads=$1 --test=oltp --oltp-table-size=10000000 \ --oltp-dist-type=uniform --oltp-table-name=sbtest_10M_$n \ --max-requests=0 --max-time=$2 --mysql-host=127.0.0.1 --mysql-port=5700 \ --mysql-user=dim --mysql-password=dim --mysql-db=sysbench \ --mysql-table-engine=INNODB --db-driver=mysql \ --oltp-point-selects=1 --oltp-simple-ranges=0 --oltp-sum-ranges=0 \ --oltp-order-ranges=0 --oltp-distinct-ranges=0 --oltp-skip-trx=on \ --oltp-read-only=on run > /tmp/test_$n.log &