將 MySQL 內部部署移轉至適用於 MySQL 的 Azure 資料庫:資料移轉
適用於:適用於 MySQL 的 Azure 資料庫 - 單一伺服器適用於 MySQL 的 Azure 資料庫 - 彈性伺服器
必要條件
備份資料庫
為求謹慎,在升級或移轉資料之前,請先匯出資料庫,然後再使用 MySQL Workbench 或透過 mysqldump
命令手動進行升級。
離線與線上的比較
選取移轉工具之前,應該先判斷移轉應於線上或離線進行。
離線移轉會導致系統在進行移轉時關閉。 此選項可確保不會發生任何交易,且資料的狀態正是在 Azure 中還原時所預期的狀態。
線上移轉會近乎即時地移轉資料。 當使用者或應用程式耗用資料工作負載時,便適合此選項。 此程序涉及使用如
binlog
或類似的複寫方法來複寫資料。
針對 WWI,其環境具有一些複雜的網路和安全性需求,不允許在目標移轉時間範圍內針對輸入和輸出連線套用適當的變更。 這些複雜度和需求基本上不需要考慮線上方法。
注意
如需離線與線上移轉的更多詳細資料,請檢閱規劃與評量一節。
資料漂移
離線移轉策略可能會造成資料漂移。 當新修改的來源資料與已移轉的資料不同步時,就會發生資料漂移。 發生這種情況時,需要完整匯出或差異匯出。 您可以停止資料庫的所有流量,然後執行匯出,藉以減輕此問題。 如果無法停止所有資料修改流量,則必須考慮漂移。
如果資料庫數據表沒有數值主鍵之類的數據行,或某些類型的修改,並在需要移轉的每個數據表中建立日期,則判斷變更可能會變得複雜。
例如,如果存在以數值為基礎的主索引鍵,且移轉是以排序次序匯入,則判斷匯入停止的位置,並從該位置重新開始則相對簡單。 如果沒有以數值為基礎的索引鍵,則可以利用修改和建立日期,然後再次以排序的方式匯入,以便您可以從目標中看到的最後一個日期重新開始移轉。
效能建議
Export
使用可在多執行緒模式中執行的匯出工具,例如 mydumper
使用 MySQL 8.0 時,請適當地使用資料分割資料表來提升匯出速度。
Import
載入資料之後先建立叢集索引和主索引鍵。 以主索引鍵順序載入資料,或者,針對主索引鍵某些日期資料行 (例如修改日期或建立日期) 以排序次序載入資料。
延遲建立次要索引,直到載入資料。 載入之後建立所有次要索引。
載入之前停用外部索引鍵限制式。 停用外部索引鍵檢查會提供顯著的效能提升。 啟用限制式並且確認載入之後的資料,以確保參考完整性。
平行載入資料。 避免會導致資源爭用的太多平行處理原則,以及使用 Azure 入口網站中可用的計量監視資源。
執行移轉。
備份資料庫
建立並驗證 Azure 登陸區域
設定來源伺服器參數
設定目標伺服器參數
匯出資料庫物件 (結構描述、使用者等)
匯出資料
匯入資料庫物件
匯入資料
驗證
重設目標伺服器參數
移轉應用程式
通用步驟
無論使用何種路徑,仍必須執行通用步驟:
升級至支援的 Azure MySQL 版本
清查資料庫物件
匯出使用者和權限
移轉至最新的 MySQL 版本
由於 WWI Conference 資料庫執行的是 5.5,因此必須執行升級。 CIO 要求他們升級至最新版的 MySQL (目前為 8.0)。
升級至 8.0 的方式有兩種:
就地
匯出/匯入
決定進行升級時,請務必執行升級檢查工具,以判斷是否有任何衝突。 例如,升級至 MySQL Server 8.0 時,此工具會檢查下列衝突:
與 MySQL 8.0 中保留字衝突的資料庫物件名稱
使用 utf8mb3 字元集
使用 ZEROFILL/ 顯示長度類型屬性
與 8.0 中資料表衝突的資料表名稱
時態性類型使用方式
外部索引鍵條件約束名稱長度超過 64 個字元
如果升級檢查程式回報沒有問題,您可以藉由取代 MySQL 二進位檔,安全地進行就地升級。 需要匯出具有問題的資料庫,並解決問題。
WWI 案例
成功將 MySQL 執行個體移轉至 8.0 之後,WWI 移轉小組發現原始資料移轉服務 (DMS) 移轉路徑無法再用作 DMS 工具,目前僅支援 5.6 和 5.7。 DMS 需要網路存取。 WWI 移轉小組尚未準備好處理其複雜的網路問題。 這些環境變數已將其移轉工具的選擇限縮為 MySQL Workbench。
資料庫物件
如「測試計畫」一節所述,移轉前後應該完成資料庫物件的清查,以確保您已移轉所有項目。
如果您想要執行預存程序來產生這項資訊,則可以使用類似下列的內容:
DELIMITER //
CREATE PROCEDURE `Migration_PerformInventory`(IN schemaName CHAR(64))
BEGIN
DECLARE finished INTEGER DEFAULT 0;
DECLARE tableName varchar(100) DEFAULT "";
#get all tables
DECLARE curTableNames
CURSOR FOR
SELECT TABLE_NAME FROM information_schema.tables where TABL
E_SCHEMA = schemaName;
-- declare NOT FOUND handler
DECLARE CONTINUE HANDLER
FOR NOT FOUND SET finished = 1;
DROP TABLE IF EXISTS MIG_INVENTORY;
CREATE TABLE MIG_INVENTORY
(
REPORT_TYPE VARCHAR(1000),
OBJECT_NAME VARCHAR(1000),
PARENT_OBJECT_NAME VARCHAR (1000),
OBJECT_TYPE VARCHAR(1000),
COUNT INT
)
ROW_FORMAT=DYNAMIC,
ENGINE='InnoDB';
INSERT INTO MIG_INVENTORY (REPORT_TYPE,OBJECT_NAME, OBJECT_TYPE, COUNT)
SELECT
'OBJECTCOUNT', 'TABLES', 'TABLES', COUNT(*)
FROM
information_schema.tables
where
TABLE_SCHEMA = schemaName;
#### Constraints
INSERT INTO MIG_INVENTORY (REPORT_TYPE,OBJECT_NAME, OBJECT_TYPE, COUNT)
SELECT
'OBJECTCOUNT', 'STATISTICS', 'STATISTICS', COUNT(*)
FROM
information_schema.STATISTICS
WHERE
TABLE_SCHEMA = schemaName;
INSERT INTO MIG_INVENTORY (REPORT_TYPE,OBJECT_NAME, OBJECT_TYPE, COUNT)
SELECT
'OBJECTCOUNT', 'VIEWS', 'VIEWS', COUNT(*)
FROM
information_schema.VIEWS
WHERE
ROUTINE_TYPE = 'FUNCTION' and
ROUTINE_SCHEMA = schemaName;
INSERT INTO MIG_INVENTORY (REPORT_TYPE,OBJECT_NAME, OBJECT_TYPE, COUNT)
SELECT
'OBJECTCOUNT', 'PROCEDURES', 'PROCEDURES', COUNT(*)
FROM
information_schema.ROUTINES
WHERE
ROUTINE_TYPE = 'PROCEDURE' and
ROUTINE_SCHEMA = schemaName;
INSERT INTO MIG_INVENTORY (REPORT_TYPE,OBJECT_NAME, OBJECT_TYPE, COUNT)
SELECT
'OBJECTCOUNT', 'EVENTS', 'EVENTS', COUNT(*)
FROM
information_schema.EVENTS
WHERE
EVENT_SCHEMA = schemaName;
INSERT INTO MIG_INVENTORY (REPORT_TYPE,OBJECT_NAME, OBJECT_TYPE, COUNT)
SELECT
'OBJECTCOUNT', 'USER DEFINED FUNCTIONS', 'USER DEFINED FUNCTIONS'
, COUNT(*)
FROM
mysql.func;
INSERT INTO MIG_INVENTORY (REPORT_TYPE,OBJECT_NAME, OBJECT_TYPE, COUNT)
SELECT
'OBJECTCOUNT', 'USERS', 'USERS', COUNT(*)
FROM
mysql.user
WHERE
user <> '' order by user;
OPEN curTableNames;
getTableName: LOOP
FETCH curTableNames INTO tableName;
IF finished = 1 THEN
LEAVE getTableName;
END IF;
SET @s = CONCAT('SELECT COUNT(*) into @TableCount FROM ', schemaName,
'.', tableName);
#SELECT @s;
PREPARE stmt FROM @s;
EXECUTE stmt;
INSERT INTO MIG_INVENTORY (REPORT_TYPE,OBJECT_NAME, OBJECT_TYPE, COUNT)
SELECT
'TABLECOUNT', tableName, 'TABLECOUNT', @TableCount;
DEALLOCATE PREPARE stmt;
END LOOP getTableName;
CLOSE curTableNames;
SELECT * FROM MIG_INVENTORY;
END //
DELIMITER ;
CALL Migration_PerformInventory('reg_app');
- 在來源資料庫上呼叫此程序會顯示下列內容 (截斷輸出):
- 完成移轉之後,目標資料庫程序結果應該類似於下圖。 請注意,資料庫中沒有函式。在移轉之前已排除函式。
使用者和權限
成功的移轉需要將相關聯的使用者和權限移轉至目標環境。
使用下列 PowerShell 指令碼來匯出所有使用者及其授與:
$username = "yourusername";
$password = "yourpassword";
mysql -u$username -p$password --skip-column-names -A -e"SELECT CONCAT('SHOW G
RANTS FOR ''',user,'''@''',host,''';') FROM mysql.user WHERE user<>''" > Show
Grants.sql;
$lines = get-content "ShowGrants.sql"
foreach ($line in $lines)
{
mysql -u$username -p$password --skip-column-names -A -e"$line" >> AllGrants.sql
}
使用 PowerShell ISE 建立新的 PowerShell 指令碼 (請參閱安裝文件)
將使用者名稱設定為 root,並將密碼設定為根用戶的密碼
然後,您可以執行以新適用於 MySQL 的 Azure 資料庫為目標的 AllGrants.sql
指令碼:
$username = "yourusername";
$password = "yourpassword";
$server = "serverDNSname";
$lines = get-content "AllGrants.sql"
foreach ($line in $lines)
{
mysql -u$username -p$password -h$server --ssl-ca=c:\temp\BaltimoreCyberTrus
tRoot.crt.cer --skip-column-names -A -e"$line"
}
您也可以使用 PowerShell 在適用於 MySQL 的 Azure 資料庫中建立使用者:/en-us/azure/mysql/howto-create-users
執行移轉
有了基本移轉元件,現在可以繼續進行資料移轉。 先前導入了數個工具和方法。 針對 WWI,這些方法將會利用 MySQL Workbench 路徑來匯出資料,然後將其匯入適用於 MySQL 的 Azure 資料庫。
資料移轉檢查清單
瞭解環境的複雜度,以及線上方法是否可行。
考慮資料漂移。 停止資料庫服務可能會消除潛在的資料漂移。
設定快速匯出的來源參數。
設定快速匯入的目標參數。
測試與目標具有不同來源版本的任何移轉。
移轉任何非資料型物件,例如使用者名稱和權限。
請確定在執行移轉時記錄並完成所有工作。