在不停機的情況下更改大表
我有一個非常大的表,讓我們呼叫它
example
,然後我嘗試在該表上執行一些更改命令:ALTER TABLE `example` ADD `example_column` TINYINT(1) NOT NULL DEFAULT 0;
檢查 alter 命令的進度:
mysql -e 'show engine innodb status \G' | grep 'undo \| log \| entries'
給我很好的資訊,關於時間 - 或多或少需要 17 天才能完成……
更改阻塞表,因此阻塞生產表 17 天不是一個好的選擇。;)
我嘗試在網上調查一些很棒的工具,例如:
- Pt-online-schema-change - Percona
- gh-ost - GitHub 的 MySQL 線上模式遷移
我還閱讀了文件,以及上述工具的限制部分:
- 根本不支持觸發器
- 根本不支持外鍵
- 觸發器的使用意味著如果表上已經定義了任何觸發器,則該工具將無法工作。
- 不提供任何更改包含外鍵的表的好方法
我的範例表有觸發器和外鍵……
你能給我一些建議,如何處理這個改變?
我有 MySQL 5.6。我使用 GTID(基於行)複製。
我將非常感謝您的建議!
你最好像這樣執行 ALTER TABLE
ALTER TABLE `example` ADD `example_column` TINYINT(1) DEFAULT NULL, ALGORITHM=INPLACE, LOCK=NONE;
有什麼好處?定義預設值為 is 的列
NULL
不會嘗試增加行的大小。對於VARCHAR
. 老實說,我不確定這是否適用於數字。(INT、TINYINT 等)。您需要對此進行測試(我在 2 年前提到過對此進行測試(InnoDB 是否允許將列添加到具有並發 READ/WRITE 行的表中?))。因此,不應該有停機時間。這樣做的缺點是更改您的軟體以處理
NULL
數字列。如果您擔心外鍵,請事先在會話中將其關閉
SET foreign_key_checks = 0; ALTER TABLE `example` ADD `example_column` TINYINT(1) DEFAULT NULL, ALGORITHM=INPLACE, LOCK=NONE;
如果您有觸發器並且可以在載入期間沒有它,請放下觸發器,執行
ALTER TABLE
並重新創建觸發器。警告:確保您使用的是最新版本的 MySQL 5.6(至少 5.6.23)以避免
ALTER TABLE
.請注意,我沒有提到使用第三方工具。這只是直接的 MySQL。
試一試 !!!
零停機時間、觸發器或 FK 或複制等沒有問題怎麼樣?
好的,有一個問題。您將創建另一個表來包含 PK 和新列。需要新列的查詢需要進行 JOIN。但是,在某些情況下,這並不是一個嚴重的缺點。
而且,
JOIN
通常需要LEFT JOIN
這樣才能NULL
在(還沒有)新列的值時獲得。使用與原始表相同的 PK 列創建新表,但沒有
AUTO_INCREMENT
. 在新表中有新列。