type
status
date
slug
summary
tags
category
icon
password

確認 DDL 項目決定更新方式

notion image

MySQL Online DDL

gh-ost 方案

事前設定

執行步驟

  1. system variables 檢查
    1. 不要帶入 --execute 進行簡易測試
      1. 若以上測試後沒有問題可以正式執行
        1. 若在非正式環境,可以在切換前直接比較新舊表的部分資料;若在正式環境,可以在切換前到 備份機 stop slave 後,徹底比較新舊表的資料更安心
        1. 確定要切換表之後,開啟另外一個視窗,刪除 postpone-cut-over-flag-file 指定的檔案
          1. 於 loading 較低的時段執行刪除舊表的動作

            特殊情況

            _gho(或_ghc) already exists 或 sock: bind:address already in use

            當發生錯誤: _gho(或_ghc) already exists 或 sock: bind:address already in use,有可能是 上一次遷移失敗 或者 已經有gh-ost在遷移該張表,如果是 上一次遷移失敗 請刪除 table OR socket 即可正常運作。

            如果沒有Slave,如何使用 gh-ost 呢?

            [error] binlogstreamer.go:77 close sync with err: sync is been closing...

            成功執行完畢後出現以下錯誤,若DDL有正常執行可以忽略

            ERROR Error 1146: Table 'account_proxy._sms_validate_code_ghc' doesn't exist

            成功執行完畢後出現以下錯誤,若DDL有正常執行可以忽略

            gh-ost 執行過程出現 ERROR 1364

            當執行 gh-ost 途中出現 ERROR 1364 如下錯誤:
            這個原因通常是發生在新增一個 NOT NULL 且沒有 DEFAULT 值的欄位的時候,因為 gh-ost 預設會如下在 session 加上嚴格模式:
            我們都知道當 sql_mode 在嚴格模式 (STRICT_ALL_TABLES) 之下時,對於 NOT NULL 沒有預設值的欄位如果在 insert intoreplace into 沒有給值,就會導致噴錯 doesn't have a default value 而無法新增。
            接下來讓我們複習一下 gh-ost 是如何作資料遷移的:
            應用類型
            原表操作
            新表操作
            Row Copy
            SELECT
            INSERT IGNORE INTO
            Binlog Apply
            INSERT
            REPLACE INTO
            對於原表已經存在的資料 gh-ost 是採用 INSERT IGNORE INTO 來寫到 _gho 表,所以雖然一樣會發生 ERROR 1364,但是 IGNORE 操作只會 warnings 提示,而不會阻擋 INSERT,如下事例:
            對於 gh-ost 執行期間 INSERT 進來的新資料是採用 REPLACE INTO 來寫到 _gho 表,會發生 ERROR 1364 並被阻擋 INSERT,如下事例:
            解決方法有兩種:
            1. NOT NULL 欄位都加上默認的 defaults 屬性
            1. 確保 GLOBAL sql_mode 在非嚴格模式時,可以在 gh-ost 添加 --skip-strict-mode 選項。 添加此選項後 gh-ost 的 session 連線就不會主動設定嚴格模式了,如下:

              手動暫時停止 gh-ost 帶來的 loading

              如何中斷 gh-ost

              調整 gh-ost loading 相關的參數

              如何調整 primary key

              由於 gh-ost要求每次遷移新表和舊表必須共享一個 唯一且NOT NULLKEY(只需要欄位相同,不需要同名)。因此如果當表中只有 primary key時,無法直接調整 primary key,而是需要先新增一個 unique key,再第二次遷移時才能調整 primark key

              如何解決 Unexpected database port

              當對雲服務商的 rds 或者 docker--port 指定為非 3306 時,會因為其內部確實是 3306 而導致未通過驗證,此時可以透過使用 --aliyun-rds--gcp 來跳過驗證。

              gh-ost 偷吃步

              只跑一次 gh-ost 的偷吃步方法,因為 gh-ost 只有在一開始會驗證新舊表是否可以搬遷,所以可以等 gh-ost 建立完新表 gho 後,先暫停複製資料的過程,我們則可以進到 DB 手動 ALTER 新表 gho,此方法可以用來越過某些限制,但可能造成資料損毀,請明確知道自己在做什麼才能使用!

              pt-osc 方案

              執行

              1. 給予super權限
                1. 基本測試
                  1. 正式執行
                    1. 如果要手動切換 table-
                      1.