Facebook 把 InnoDB 換成 MyRocks 的計畫

在「Migrating a database from InnoDB to MyRocks」這邊講到了 FacebookMySQL 的 InnoDB 換成 MyRocks 的計畫。

Facebook 已經大量導入全 Flash 的環境,於是現在 InnoDB (Compressed) 的情況類似於這樣:

可以看到空間是最大的問題 (Space-bound),而非 CPU 或是 I/O,這在純 Flash 的機器上還蠻有可能的,因為純 Flash 能提供的 I/O capacity 超高,加上 Facebook 把 MySQL 當作後端儲存設備而已,CPU 的使用量可以預期不高...

然後他們估算 MyRocks 可以省下一半的空間,於是有可能變成:

不過對於一般單位來說,這些前提就未必成立了... 但還是可以看到 Mark Callaghan 花不少力氣在調校一般性的效能,希望讓使用者多一點...

InnoDB 與 MyRocks 之間的取捨

MyRocks 的主要作者 Mark Callaghan 整理了一篇關於大台機器下,資料可以放到記憶體內的效能比較:「In-memory sysbench, a larger server and contention - part 1」。

這其實才是一般會遇到的情況:當事業夠大時,直接花錢買 1TB RAM + 數片 PCI-E SSD 的機器用錢換效能... (主要應該會在記憶體花不少錢,剛剛查了一下,現在白牌的 server 一台大約七十萬就可以擺平?兩台做 HA 也才一百四十萬,對有這個規模的單位來說通常不是大問題...)

而三種不同的 case 裡面,最後這個應該是最接近真實情況的:

可以看到 InnoDB 在幾乎所有項目都還是超越 MyRocks (只有 random-points 與 insert-only 輸)。

不知道後續的開發能量還會有多少... (因為 Facebook 的用法跟一般情況不一樣)

MySQL 上不同 Isolation Level 對效能的影響

目前看到的結論都是:MySQL (InnoDB) 上因為高度對 RR (REPEATABLE-READ) 最佳化,使得 RR 的效能反而比 RC (READ-COMMITTED) 以及 RU (READ-UNCOMMITTED) 都好。

不清楚 RR/RC/RU 差異的可以參考維基百科上「Isolation (database systems)」的解釋...

從 2010 年在測 5.0 的「Repeatable read versus read committed for InnoDB」到 2015 年測 5.7 的「MySQL Performance : Impact of InnoDB Transaction Isolation Modes in MySQL 5.7」都測出 RR 的效能比 RC/RU 好... 三段分別是 RR/RC/RU:

所以在 MySQL 上沒有使用 RC/RU 的必要... (抱頭)

小台機器上的 innodb_purge_threads 對效能的影響

雖然「MyISAM, small servers and sysbench at low concurrency」這篇標題是在講 MySQL 上的 MyISAM,但還是有提到一些 InnoDB 的東西...

其中提到了 innodb_purge_threads 對效能的影響:

the default value for innodb_purge_threads, which is 4, can cause too much mutex contention and a loss in QPS on small servers. For sysbench update-only I lose 25% of updates/second with 5.7.17 and 15% with 8.0.1 when going from innodb_purge_threads=1 to =4.

當機器不大的時候,innodb_purge_threads 對於效能帶來的影響其實頗大的?

另外從作者最近的一系列測試看起來,5.7 在小機器的效能比 5.6 差不少... 這點在考慮 RDS 的時候也許要注意 (因為 t2.* 應該不算大 XD)。

MySQL 上 Replication 的方案

Percona 的人整理了一篇關於 Replication 的方案 (以及 NDB,不過這邊就先偷偷跳過去...),雖然標題寫的是 High Availability:「The MySQL High Availability Landscape in 2017 (The Elders)」。

先講他給的另外兩個方案,一個是 Shared Storage,另外一個是 NDB。

其中 Shared Storage 其實在儲存空間端還是有單點失效的問題,而 NDB 的特性跟 InnoDB 不同,有很多概念要重新學... 如果就這三個比較,常見的還是第一個提到的 Replication。

其實把 Replication 用熟的話已經可以解決不少問題了 (不論是早期的 MMM,或是 MHA)。而且因為技術已經發展很久了,大家幾乎都很熟特性 (以及 bug XD),網路上可以找到不少資料,甚至 Percona 也都能夠支援 (當你願意付錢的時候 XDDD)。

MySQL 總算要拔掉 mysql_query_cache 了

半官方的 MySQL blog 上宣佈了拔掉 mysql_query_cache 的計畫:「MySQL 8.0: Retiring Support for the Query Cache」。

作者開頭引用了 ProxySQL 的人對 MySQL Query Cache 的說明:

Although MySQL Query Cache was meant to improve performance, it has serious scalability issues and it can easily become a severe bottleneck.

主要問題在於 MySQL Query Cache 在多 CPU 環境下很難 scale,很容易造成一堆 thread 在搶 lock。而且作者也同意 ProxySQL 的說法,將 cache 放到 client 的效能比較好:

We also agree with Rene’s conclusion, that caching provides the greatest benefit when it is moved closer to the client:

可以看到 Query Cache 在複雜的環境下對效能極傷。而之前也提到過類似的事情了:「Percona 對 mysql_query_cache 的測試 (以 Magento 為例)」、「關閉 MySQL 的 Query Cache」。

一般如果要 cache 的話,透過 InnoDB 裡良好的 index 應該還可以撐不少量起來。

InnoDB redo log 大小對效能的影響

在「Benchmark(et)ing with InnoDB redo log size」這邊看到在討論 InnoDB redo log 的大小對效能的影響 (也就是 innodb_log_file_sizeinnodb_log_files_in_group)。

開頭就有先提到重點,在新版 MySQL 裡,幾乎所有的情況比較大的 redo log 有比較好的效能 (平均值):

tl;dr - conclusions specific to my test

  1. A larger redo log improves throughput
  2. A larger redo log helps more with slower storage than with faster storage because page writeback is more of a bottleneck with slower storage and a larger redo log reduces writeback.
  3. A larger redo log can help more when the working set is cached because there are no stalls from storage reads and storage writes are more likely to be a bottleneck.
  4. InnoDB in MySQL 5.7.17 is much faster than 5.6.35 in all cases except IO-bound + fast SSD

可以看出來平均效能的提昇很顯著,不管是增加 redo log 大小還是升級到 5.7:

但作者也遇到了奇怪的效能問題。雖然平均效能提昇得很顯著,但隨著加入資料的增加,效能的 degradation 其實很嚴重,在原來的網頁上可以看到這些資訊。

The results above show average throughput and that hides a lot of interesting behavior. We expect throughput over time to not suffer from variance -- for both InnoDB and for MyRocks. For many of the results below there is a lot of variance (jitter).

所以也許現階段先加大就好 (至少寫入的效能會提昇),不需要把這個特性當作升級 MySQL 的理由。

Oracle 官方的 InnoDB Cluster 出 GA 了...

Oracle 推出的 InnoDB Cluster 進入 GA 了,不過先觀望看看就好:「MySQL InnoDB Cluster GA is Available Now!」。

The GA release of InnoDB Cluster builds upon the great work that the MySQL Development Team has done on Group Replication, filling out the rest of the stack for setup, management, orchestration, and client routing.

算是 Galara Cluster 的競爭對手 (被 PerconaMariaDB 採用),產品成熟度還得再看如何...

在 MySQL InnoDB 下單表復原的方式

在「How to Restore a Single InnoDB Table from a Full Backup After Accidentally Dropping It」這篇提到了 MySQL InnoDB 單表復原的事情。

文章裡先提到了 2012 年的文章「How to recover a single InnoDB table from a Full Backup」,講更特定的情況。

這邊兩篇的大前提都是使用 innodb_file_per_table

2012 的文章裡講的是誤刪 (DELETE) 後的處理,如果是 DROP TABLETRUNCATE 或是因為 ALTER TABLE 而造成資料遺失的話,就不能用這篇文章的方式處理:

You must not drop, truncate or alter the schema of the table after the backup has been taken.

如果很幸運是因為 DELETE 而遺失的話,在文章裡有提到 innobackupex 這個工具,透過 innobackupex 備份的資料才有辦法依照文章裡的方法做到單表復原。

先 discard tablespace:

mysql> set FOREIGN_KEY_CHECKS=0;
mysql> ALTER TABLE salaries DISCARD TABLESPACE;

然後把檔案 cp 進去:

cp /tmp/2012-01-22_14-13-20/employees/salaries.ibd /var/lib/mysql/data/employees/

最後再 import tablespace 回去:

mysql> set FOREIGN_KEY_CHECKS=0;
mysql> ALTER TABLE salaries IMPORT TABLESPACE;
mysql> set FOREIGN_KEY_CHECKS=1;

而 2017 講的誤刪則是補充了 2012 文章裡另外的情況,用途也比較廣,但動作比較複雜。

本來的四個步驟:

  • Prepare the backup
  • Discard the tablespace of the original table
  • Copy .ibd from the backup to the original table path
  • Import the tablespace

變成了七個步驟:

  • Prepare the backup
  • Extract the original table structure from the backup (i.e., extract the create statement from the backup .frm file)
  • Create a new empty table
  • Apply some locks
  • Discard the newly created tablespace
  • Copy back .ibd from the backup
  • Import the tablespace

粗體的部份就是不一樣的部份,多出來的步驟產生出同樣的環境配合 .ibd,然後讓 .ibd 檔匯進 MySQL。

實際練過一次會比較有感覺 (應該可以在 Docker 裡測試),等不幸遇到的時候手腳比較不會慌亂...

Pinterest 對 InnoDB 壓縮的改善

三個月前 Pinterest 提到對 InnoDB 壓縮的改善,講到透過字典的改善方式:「Pinterest 在 InnoDB Compression 的努力」。

而在「Evolving MySQL Compression - Part 2」這邊繼續說明要怎麼生出對 Pinterest 比較有效的字典內容,作者把計算的工具放到 GitHub 上讓其他人可以用 (用 Python 寫的):「pinterest/mysql_utils/zdict_gen/」。

可以看出來又增加不少壓縮率,這算是針對資料庫壓縮從 A 到 A+ 的行為吧...