Multithreading 版本 pt-online-schema-change

看起來是個嘗試,Percona 的人試著修改 pt-online-schema-change,讓他可以在 INSERT 時 multi-threading,然後看效果:「Multithreaded ALTER TABLE with pt-online-schema-change and myloader」。

可以看出來 thread 夠多的情況下其實都變快不少 (上圖主要是看絕對數字,下圖是看相對比率):

如果沒有意外的話應該會有更多的測試,而這些測試沒問題的話,之後的官方版本裡面應該就會有這個功能。

Runtime 期間的最佳化工具:Dynimize

忘記在哪邊看到「Reduce MySQL CPU Usage Through Dynamic Binary Optimization」這篇文章了,裡面其實是在描述自家產品 Dynimize 的威猛。

翻了一些資料可以發現這個產品出來一陣子了,在 2018 的時候曾經在 Percona Live 上發表過:「Accelerating MySQL with JIT Compilers」,可以看出來有點像是 PGO (Profile-guided optimization) 的行為,只是他可以直接對 binary 處理。

定價的部份會是這類產品的重點,如果價錢比加硬體貴的話就沒那麼好用了... 在 Dynimize Pricing 這邊可以看到是 per CPU 的價錢,$0.00139/hr、$1/month 或是一次性的 $24,以效能提昇的程度來看,如果在 database 這邊是 CPU bound,是個頗值得投資的項目。

MySQL (InnoDB) 的內部狀態

Percona 老大 Peter Zaitsev 在「MySQL – A Series of Bad Design Decisions」這篇裡提到了他認為 MySQL 設計上的問題,不過裡面也提到了不少有用的指令,平常可以先熟悉一下輸出,等真的有狀況的時候才會想起來可以用這些指令。

首先是最經典的 SHOW ENGINE INNODB STATUS,算是很多文件上面都會提到的指令。可以看 InnoDB 當下的情況,藉以猜測內部現在是怎麼卡住...

另外一個是 SHOW ENGINE INNODB MUTEX,就如同 Peter Zaitsev 所提到的,這個指令想辦法抓出最重要的資訊,但不要像 SHOW ENGINE INNODB STATUS 給了那麼多。

另外當然就是 INFORMATION_SCHEMA,他甚至希望 SHOW ENGINE INNODB 系列的指令應該要被整合進去,這樣才能用 SELECT 相關的指令整理... (因為 ORDER BY 以及蠻多的指令沒辦法在 SHOW ... 上面用)

Amazon RDS 推出了 Connection Pool 的產品

Amazon RDS 推出了 Connection Pool 的產品,叫做 Amazon RDS Proxy:「Introducing Amazon RDS Proxy (Preview)」。

目前支援 MySQL (包括了傳統的與 Aurora 版本的):

Amazon RDS Proxy supports Amazon RDS for MySQL and Amazon Aurora with MySQL compatibility, with support for additional RDS database engines coming soon.

定價策略看起來是依照後端資料庫的 vCPU 計算:

Pricing is simple and predictable: you pay per vCPU of the database instance for which the proxy is enabled.

翻了一下價錢頁是 USD$0.015/vCPU (用 us-east-1 的資料),而如果是 t2 系列的機器,最低是以 2 vCPUs 計算,不是照使用比例算:

RDS Proxy pricing correlates to the number of vCPUs of the database instance for which it is enabled, with a minimum charge for 2 vCPUs.

這樣一個 vCPU 一個月大約要 USD$21.6,算起來頗貴的... 如果 SLA 允許的話,用基本的方式 failover 也許就 ok 了...

如果 SLA 真的要追求到這麼高的話,可以在這些區域測試:

Amazon RDS Proxy is available in preview for RDS MySQL and Aurora MySQL in US East (N. Virginia), US East (Ohio), US West (Oregon), EU West (Ireland), and Asia Pacific (Tokyo) regions. Support for RDS PostgreSQL and Aurora PostgreSQL is coming soon.

Amazon Aurora 可以直接使用 AWS 的 Machine Learning 服務

AWS 宣佈了 Amazon Aurora 可以直接使用 AWS 自家的 Machine Learning 服務:「New for Amazon Aurora – Use Machine Learning Directly From Your Databases」。

整合了兩個服務,分別是 Amazon SageMaker (各類的模型) 以及 Amazon Comprehend (文字處理相關)。

目前只有 Amazon Aurora MySQL 5.7 的版本有支援,其他的還在做:

The new machine learning integration is available today for Aurora MySQL 5.7, with the SageMaker integration generally available and the Comprehend integration in preview. You can learn more in the documentation. We are working on other engines and versions: Aurora MySQL 5.6 and Aurora PostgreSQL 10 and 11 are coming soon.

這個整合讓程式用起來更方便了...

Amazon Aurora MySQL 5.7 也可以上 Global Database 了

AWSAmazon Aurora MySQL 5.7 版本推出了 Amazon Aurora Global Database:「Aurora Global Database is Now Supported on Amazon Aurora MySQL 5.7」。

看起來 MySQL 系的 Global Database 就是跨區的 master-slave 架構 (所以標榜降低了 read latency,但沒有提到 write latency):

An Amazon Aurora Global Database is a single database that spans multiple AWS regions, enabling low latency global reads and disaster recovery from region-wide outages.

另外可以看到是 1 秒,所以應該是 async replication:

Aurora Global Database replicates writes in the primary region with typical latency of <1 second to secondary regions, for low latency global reads.

然後可以跨區切換:

In disaster recovery situations, you can promote the secondary region to take full read-write responsibilities in under a minute.

看了一下好像不用多付服務費用,就是各區自己的費用,加上傳輸的費用而已,看起來是個還不錯的服務?

GitLab 12.1 之後放棄支援 MySQL

GitLab 打算在 12.1 之後放掉 MySQL 的支援:「Why we're ending support for MySQL in 12.1」。

GitLab 在說明裡給了不少原因,但看了看以後還是覺得 GitLab 每次在做技術決策時給出來的理由都很... 有趣?XD

每次看這三家提供的技術工具或是技術決策都很有趣... (另外兩家是 UberYahoo!)

RDBMS 裡的各種 Lock 與 Isolation Level

來推薦其他人寫的文章 (雖然是在 Medium 上...):「複習資料庫的 Isolation Level 與圖解五個常見的 Race Conditions」、「對於 MySQL Repeatable Read Isolation 常見的三個誤解」,另外再推薦英文維基百科上的「Snapshot isolation」條目。

兩篇文章都是中文 (另外一個是英文維基百科條目),就不重複講了,這邊主要是拉條目的內容記錄起來,然後寫一些感想...

SQL-92 定義 Isolation 的時候,技術還沒有這麼成熟,所以當時在訂的時候其實是以當時的技術背景設計 Isolation,所以當技術發展起來後,發生了一些 SQL-92 的定義沒那麼好用的情況:

Unfortunately, the ANSI SQL-92 standard was written with a lock-based database in mind, and hence is rather vague when applied to MVCC systems. Berenson et al. wrote a paper in 1995 critiquing the SQL standard, and cited snapshot isolation as an example of an isolation level that did not exhibit the standard anomalies described in the ANSI SQL-92 standard, yet still had anomalous behaviour when compared with serializable transactions.

其中一個就是 Snapshot Isolation,近代的資料庫系統都用這個概念實做,但實際上又有不少差別...

另外「Jepsen: MariaDB Galera Cluster」這篇裡出現的這張也很有用,裡面描述了不同層級之間會發生的問題:

這算是當系統有一點規模時 (i.e. 不太可能使用 SERIALIZABLE 避免這類問題),開發者需要了解的資料庫限制...

RDS 支援 Storage Auto Scaling

Amazon RDS 推出了 Storage Auto Scaling:「Amazon RDS now supports Storage Auto Scaling」。

看起來傳統 RDBMS 類的都支援 (也就是非 Aurora 的這些):

Starting today, Amazon RDS for MariaDB, Amazon RDS for MySQL, Amazon RDS for PostgreSQL, Amazon RDS for SQL Server and Amazon RDS for Oracle support RDS Storage Auto Scaling.

仔細看了一下新聞稿,裡面都只有提到 scale up,沒有提到 scale down,這個功能應該是只會提昇不會下降,所以要注意突然用很多空間,再砍掉後的問題:

RDS Storage Auto Scaling automatically scales storage capacity in response to growing database workloads, with zero downtime.

RDS Storage Auto Scaling continuously monitors actual storage consumption, and scales capacity up automatically when actual utilization approaches provisioned storage capacity.

除了香港外的所有商業區域都提供:

RDS Storage Auto Scaling is available in all commercial AWS regions except in Asia Pacific (Hong Kong) and AWS GovCloud.

在 SQL 裡面避免大量刪除資料的方式

看到 Percona 的「An Overview of Sharding in PostgreSQL and How it Relates to MongoDB’s」這篇,雖然是在講 PostgreSQL 上的 sharding (以及 partition),突然想到好像沒寫過要怎麼避免大量刪除資料的操作...

一個常見的情境是,想要讓某個表格只保留這一個月的資料,所以每個月開頭都會跑一隻 cron job 負責刪掉上個月的資料,像是 DELETE FROM xxx WHERE timestamp < yyy; 這樣的指令。

這個方式無論是在 PostgreSQL 或是 MySQL 都需要很多時間與 I/O 資源,而透過 partition 將不同時間區段切開到不同的表格,再用 TRUNCATE 直接清空表格剛好可以解這樣的問題。

Percona 的文章裡說了一些 PostgreSQL 的歷史與目前的進展。

在 PostgreSQL 9 或更早以前的版本,一個常見的作法是透過 table inheritance 實做 partition,然後用再用 function 實做 INSERT

CREATE TABLE temperature (
  id BIGSERIAL PRIMARY KEY NOT NULL,
  city_id INT NOT NULL,
  timestamp TIMESTAMP NOT NULL,
  temp DECIMAL(5,2) NOT NULL
);

CREATE TABLE temperature_201901 (CHECK (timestamp >= DATE '2019-01-01' AND timestamp <= DATE '2019-01-31')) INHERITS (temperature);
CREATE TABLE temperature_201902 (CHECK (timestamp >= DATE '2019-02-01' AND timestamp <= DATE '2019-02-28')) INHERITS (temperature);
CREATE TABLE temperature_201903 (CHECK (timestamp >= DATE '2019-03-01' AND timestamp <= DATE '2019-03-31')) INHERITS (temperature);

CREATE OR REPLACE FUNCTION temperature_insert_trigger()
RETURNS TRIGGER AS $$
BEGIN
    IF ( NEW.timestamp >= DATE '2019-01-01' AND NEW.timestamp <= DATE '2019-01-31' ) THEN INSERT INTO temperature_201901 VALUES (NEW.*);
    ELSIF ( NEW.timestamp >= DATE '2019-02-01' AND NEW.timestamp <= DATE '2019-02-28' ) THEN INSERT INTO temperature_201902 VALUES (NEW.*);
    ELSIF ( NEW.timestamp >= DATE '2019-03-01' AND NEW.timestamp <= DATE '2019-03-31' ) THEN INSERT INTO temperature_201903 VALUES (NEW.*);
    ELSE RAISE EXCEPTION 'Date out of range!';
    END IF;
    RETURN NULL;
END;
$$
LANGUAGE plpgsql;

在 PostgreSQL 10 之後,就直接支援一些與 partition 相關的設計,像是這樣:

CREATE TABLE temperature (
  id BIGSERIAL NOT NULL,
  city_id INT NOT NULL,
  timestamp TIMESTAMP NOT NULL,
  temp DECIMAL(5,2) NOT NULL
) PARTITION BY RANGE (timestamp);

CREATE TABLE temperature_201901 PARTITION OF temperature FOR VALUES FROM ('2019-01-01') TO ('2019-02-01');
CREATE TABLE temperature_201902 PARTITION OF temperature FOR VALUES FROM ('2019-02-01') TO ('2019-03-01');
CREATE TABLE temperature_201903 PARTITION OF temperature FOR VALUES FROM ('2019-03-01') TO ('2019-04-01');

雖然還是有些限制,但可以看出比起以前簡單不少。

而有了 partition 後,文章的後續就在討論這跟 MongoDB 的 sharding 有什麼關係,但這就不是我關注的事情了...