AWS 提供跨區的 MySQL Read Replica...

Amazon RDS 將提供跨區的 MySQL read replication。看起來是針對 5.6+ 的版本提供這個功能...

有兩篇官方文章,一篇是 CTO 發了一篇「Expanding the Cloud: Enabling Globally Distributed Applications and Diaster Recovery」,另外一篇是官方網誌上的「Cross-Region Read Replicas for Amazon RDS for MySQL」。

用圖表示比較容易懂:

在 US-East 建立 MySQL master,另外在 EU 與 Tokyo 建立 slave replication。不知道中間的 traffic 有沒有過 IPSec 或是 SSL?

Galera Cluster 3.x 的設定...

Percona XtraDB Cluster 5.6 用的是 Galera Cluster 3.x 的 patch,所以 Percona 的人寫了一篇介紹 3.x 有哪些設定:「New wsrep_provider_options in Galera 3.x and Percona XtraDB Cluster 5.6」。

看起來來比較有影響的是 gmcast.segment=0,用在跨機房之間的判斷。

看起來應該是同一個機房要設一樣的 gmcast.segment。這個值會用在兩個地方:第一個是跨 segment 的 replication 流量會試著盡可能小。第二個是同步時的 Donor 會優先選擇同機房的節點。

其他的用預設值應該就 okay...

Percona XtraDB Cluster (PXC) 開始測試 5.6 版了...

Percona 的 blog 上看到 Percona XtraDB Cluster 出 5.6 版 (測試版) 了:「Percona XtraDB Cluster 5.6.14-25.1 Beta is now available」。

也就是 Galera ClusterMySQL 5.6 上的版本...

在 5.6 上有的功能都會有,也就是說,InnoDB 的 memcache interface,以及 FULLTEXT 功能都可以用?

另外在 comment 也有討論到要如何從 PXC 5.5 升級到 5.6 (不產生 downtime),看起來也是噓要花時間 PoC 過後才能確認... 就算正式釋出,應該還是會觀望看看。

熱 MySQL InnoDB 的方式...

之前寫過一篇「熱 MySQL 的方法...」,主要是利用 InnoDB 在 SELECT COUNT(*) 時會掃過一次 primary key 來熱:

pt-find --charset=utf8 --print -h $1 -u USER -p PASSWORD | xargs -t -P8 -I% -n1 sh -c "echo 'SELECT COUNT(*) FROM %;' | mysql -h $1 > /dev/null"

但想要熱整個表格時 (data 部份),這個方法就不夠力了,今天才想到可以這樣做:

SELECT COUNT(*) FROM (SELECT * FROM table_name) t;

這方法會把整個表格資料拉出來,但又不會造成大量的網路 i/o (以及洗畫面)。實際測過後發現效果還不錯... (對於 table scan 使用量很大的表格,靠這個把整個表個塞進 InnoDB buffer)

從爆炸的遺跡尋找蛛絲馬跡:在 MySQL crash 後,從 core file 找出當時有哪些 query 在執行

Percona 寫了一篇文章,說明在 MySQL core dump 後,要如何從 core file 撈出當時有哪些 query 在跑:「How to Extract All Running Queries (Including the Last Executed Statement) from a Core File?」。

一年前 Percona 的人也有寫一篇「How to obtain the “LES” (Last Executed Statement) from an Optimized Core Dump?」,今年這篇則是改良版,可以看到操作的方式便簡單了...

雖然大家都不喜歡 MySQL crash,但知道爆炸當時有哪些 query 對於後續的分析有很大的幫助,先紀錄起來,如果真的不幸用到,會比較快找到資料...

十個改善 MySQL 效能的方式

Zite 上看到這篇介紹 MySQL 效能調教的方式:「Ten ways to improve the performance of large tables in MySQL」。

這邊就順著作者的建議一路寫下去。

作者也是大力推薦用 InnoDB 解決問題。

InnoDB 有個特別的功能 (相較於 MyISAM 而言。這個功能在 MySQL 5.5 預設就是開啟的) 是 change buffering,會延遲寫入 non-unique secondary index,讓多筆 secondary index 合併起來一起寫,這會改善寫入的效能。

Partition 對於 index 的大小也會有幫助。InnoDB 的壓縮功能也是必備項目 (除非你的 Use case 很極端),減少資料量就直接減少 i/o 並且拉高 hitrate。

再大量寫入資料時依照順序寫入會讓 InnoDB 寫入的順序僅可能連續。由於 InnoDB 的特性 (clustered index),這樣可以讓寫入速度變快很多。

避免使用 UNIQUE key,因為 UNIQUE 的特性會犧牲很多效能...

因為 secondary index 是指到 PRIMARY KEY 的值,所以 PRIMARY KEY 的值僅可能單純,以 INT 或是 BIGINT 為佳。

第一次大量倒資料進系統時,可以先倒 data 以及 PRIMARY KEY 就好 (如上所說的,要依照 PRIMARY KEY 的順序倒進去),等倒完後再建立 secondary index,這樣速度會快很多。

最後兩項就是,記憶體愈大愈好,硬碟愈快愈好,如果用 SSD 是可行的方案就用 :p

Percona 的 MySQL High Availability 機制比較文

Percona 發了一篇「High-availability options for MySQL, October 2013 update」,比較目前 MySQL 上常見的 High Availability 機制。

包括了五個系統:

  • Percona XtraDB Cluster (PXC)
  • Percona replication manager (PRM)
  • MySQL master HA (MHA)
  • NDB Cluster
  • Shared storage/DRBD

這些都是把 High Availability 做在 MySQL 上,讓前端的程式不需要操心的方式。都是有個固定的 IP address 保證可以讀寫。

這五個方案都不完美,看環境需求而選擇使用。

我一般給的建議還是 Heartbeat + DRBD + InnoDB,這個方法是極為成熟的方法,會遇到的問題網路上都已經討論過了。如果找 Percona 的人支援也是完全沒問題。

用 InnoDB 時關於 PRIMARY KEY 的建議

Percona 的「InnoDB scalability issues due to tables without primary keys」這篇文章在討論 InnoDB 在沒有 PRIMARY KEY 時的效能問題。

在討論效能問題前,應該先讀過 MySQL 官方文件裡提到 InnoDB index 架構的文章,其中就有提到 PRIMARY KEY 以及其他的 INDEX KEY 的底層架構:「InnoDB Table and Index Structures」。

InnoDB 是 clustered index 架構 (關於 clustered index 的完整說明,可以參考維基百科的「Database index」條目),也就是說,資料本身 (row data) 存放時會按照某個順序存放,這邊的順序是按照這樣的方式定義的:

  • 如果你有指定 PRIMARY KEY,那麼就會直接用 PRIMARY KEY 當作 clustered index。
  • 如果沒有指定 PRIMARY KEY,但有 UNIQUE INDEX,而且所有欄位都是 NOT NULL,那麼就用這組 UNIQUE INDEX (NOT NULL) 當作 clustered index。
  • 如果都沒有指定 PRIMARY KEY,那麼就會產生一個隱藏的欄位,是一個 6 bytes 的 auto increment 的數字,用這個欄位當 clustered index。也因為如此,在這種情況下,資料會依照建立的順序存放。

另外,InnoDB 的 secondary index 會指到 PRIMARY KEY (B+Tree 的 value 部分是放 PRIMARY KEY)。

所以,一般在規劃資料庫時建議的作法是:

  • 所有的表格都要有 PRIMARY KEY。
  • PRIMARY KEY 必須是 INT UNSIGNED (4 bytes),只有在需要 BIGINT UNSIGNED (8 bytes)的時候才用 BIGINT UNSIGNED。

對於有大量 secondary index 的表格更應該這樣做 (因為可以省下大量空間)。而對於現代的 ORM 來說,也都幾乎要求要有 PRIMARY KEY,甚至有些 ORM 要求 PRIMARY KEY 必須是 single column。

如果你都能了解後,再去看 Percona 討論沒有 PRIMARY KEY 的情況時,才能了解他們想要討論什麼事情... 裡面還包含了 InnoDB 格式的差異。

將 latin1 的表格轉換成 UTF-8 表格...

Percona 的人寫了一篇「utf8 data on latin1 tables: converting to utf8 without downtime or double encoding」,告訴你怎麼將 latin1 的 TEXT 欄位轉成 UTF-8,文章內有提到利用 BLOB 轉。

不確定同樣方式能不能做在 VARCHAR 上面 (用 BINARY 轉?),但不知道會不會有 UNIQUE + prefix support 的問題?有遇到再來測試看看...