
# 场景一：数据中心自建MySQL迁移到DDM
#### 场景介绍
企业当前使用数据中心自建MySQL，希望能使用DDM将数据进行分布式存储。
![](https://support.huaweicloud.com/usermanual-ddm/public_sys-resources/notice_3.0-zh-cn.png)
迁移过程中可能会出现业务中断情况，中断时长与迁移数据量大小、网络情况相关。
#### 迁移示意图
图1数据中心自建MySQL迁移到DDM示意图   
![](https://support.huaweicloud.com/usermanual-ddm/zh-cn_image_0000001613736832.png)
#### 约束限制
- 目标DDM实例、RDS for MySQL实例所在ECS必须保证网络互通。
- 为了保持数据完整性，需要先停止业务后再进行数据迁移。
- DDM不支持以自动新建库或者新建拆分表、广播表的方式导入数据。因此导入数据前需要先创建好相同名称的逻辑库，相同拆分表、广播表结构的逻辑表，然后再进行数据导入。各类逻辑表创建方式请参见[表2]。
- 目标DDM使用的RDS for MySQL实例与自建MySQL的MySQL版本需要保持一致。
 
#### 迁移前准备
- 准备可以访问自建MySQL所在数据中心的ECS。
  1. 确保自建MySQL所在数据中心和目标DDM实例、RDS for MySQL实例都与ECS网络互通。
  
  2. ECS已安装MySQL官方客户端，MySQL客户端版本建议为5.6或5.7。
     - Red Hat系列Linux安装命令：**yum install mysql mysql-devel**
     
     - Debian系列Linux安装命令：**apt install mysql-client-5.7 mysql-client-core-5.7**
      
  
  
  
  3. ECS磁盘空间足够存放临时转储文件；ECS内存空间足够，可以用来比较转储文件。
   

- 准备DDM实例，并配置DDM账号、DDM逻辑库、DDM逻辑表等相关信息。
  1. 申请DDM实例，并在DDM控制台创建DDM账号、创建逻辑库。
  
  2. 导出自建MySQL数据表结构至SQL文本文件。
     - MySQL客户端版本为5.6和5.7时请执行以下命令：
       ```
       mysqldump -h {DB_ADDRESS} -P {DB_PORT} -u {DB_USER} -p --no-data --skip-add-locks --add-locks=false --skip-tz-utc {DB_NAME} {TABLE_NAME} > {mysql_table_schema.sql}
       ```
       
     
     - MySQL客户端版本为8.0时请执行以下命令：
       ```
       mysqldump -h {DB_ADDRESS} -P {DB_PORT} -u {DB_USER} -p --no-data --skip-add-locks --add-locks=false --column-statistics=0 --skip-tz-utc {DB_NAME} {TABLE_NAME} > {mysql_table_schema.sql}
       ```
       
     
     
     相关参数解释如[表1]所示。
      表1参数解释 
     | 参数                     | 说明                            | 备注                                                                                                                 |
     |:---|:---|:---|
     | DB_ADDRESS             | 待导出数据的数据库连接地址。                | 必填                                                                                                                 |
     | DB_PORT                | 数据库侦听端口                       | 必填                                                                                                                 |
     | DB_USER                | 数据库用户                         | 必填                                                                                                                 |
     | --skip-lock-tables     | 在不锁表的情况下导出数据。                 | 某些参数会默认开启加锁声明，因此建议在数据导出语句末尾增加此参数。                                                                                  |
     | --add-locks=false      | 导出的数据文件中不加锁表的声明。              | -                                                                                                                  |
     | --no-data              | 不导出任何数据，只导出数据库表结构。            | 导出表结构时使用。                                                                                                          |
     | --column-statistics=0  | 如果使用的MySQL客户端版本为8.0，则必须关闭该特性。 | MySQL客户端版本为8.0时必填。                                                                                                 |
     | DB_NAME                | 数据库名称                         | 必填                                                                                                                 |
     | TABLE_NAME             | 表名                            | 可以多个同类型的表，用空格隔开。建议只导出与业务相关的表结构                                                                                     |
     | mysql_table_schema.sql | 生成的表结构文件名。                    | 每次导出表结构时文件名不同。 建议以"逻辑库名"+"_"+"逻辑表名"+"_"+"schema"格式命名，以免数据被覆盖。如mysql_table_schema.sql。 |
        
     ![](https://support.huaweicloud.com/usermanual-ddm/public_sys-resources/note_3.0-zh-cn.png)
     此处举例的参数为数据导出中常用的参数，由于mysqldump参数无法逐一列举，如果存在个别参数调优等特殊情况，请在MySQL官网查询。
     
  
  3. 创建逻辑表。
     创建逻辑表结构请与[2]中导出的表结构保持一致，把源表映射到目标DDM实例逻辑表，明确对应表结构和表数据的迁移策略，如[表2]所示。
     ![](https://support.huaweicloud.com/usermanual-ddm/public_sys-resources/note_3.0-zh-cn.png)
     创建前可先通过SQL语句：show create table **{TABLE_NAME}**查看自建MySQL中数据表结构。
      表2表迁移策略 
     | 逻辑库类型 | 逻辑表类型 | 表结构迁移策略                                                     | 表数据迁移策略      |
     |:---|:---|:---|:---|
     | 拆分    | 拆分表   | 在原表结构基础上增加拆分键声明（详见建表语句说明文档），形成适用于DDM的建表语句，连接DDM并登录对应逻辑库后执行。 | 通过DDM导入源表数据。 |
     | 拆分    | 广播表   | 在原表结构基础上增加广播声明（详见建表语句说明文档），形成适用于DDM的建表语句，连接DDM并登录对应逻辑库后执行。  | 通过DDM导入源表数据。 |
     | 拆分    | 单表    | 获取原表建表语句，连接DDM并登录对应逻辑库后执行。                                  | 通过DDM导入源表数据。 |
     | 非拆分   | 单表    | 获取原表建表语句，连接DDM并登录对应逻辑库后执行。                                  | 通过DDM导入源表数据。 |
        
     
  
  
  
  4. 清理目标DDM实例的测试数据，防止和待迁移数据冲突。
   
- 准备RDS for MySQL实例。
 
#### 导出数据
此处以本地IP连接的方式介绍，通过使用mysqldump工具来导出数据。
在进行数据导出操作之前，您需要做到以下两点：
- 保障DDM实例的子网及虚拟私有云与客户端ECS实例保持一致。
- 放通安全组入方向规则。
 
从数据中心自建MySQL中将表数据导出到单独的SQL文本文件中，然后上传至ECS。
1. 停止自建MySQL的业务系统，否则可能会导致导出数据不是最新的。
2. 打开MySQL客户端，输入如下命令，连接自建MySQL，并导出自建MySQL表数据至SQL文本文件。 
   - MySQL客户端版本为5.6和5.7时请执行以下命令：
     ```
     mysqldump -h {DB_ADDRESS} -P {DB_PORT} -u {DB_USER} -p --single-transaction --hex-blob --complete-insert --set-gtid-purged=OFF --quick --no-create-info --skip-comments  --skip-add-locks --add-locks=false --skip-tz-utc [--where=""] {DB_NAME}{TABLE_NAME} > {mysql_table_data.sql}
     ```
     
   
   - MySQL客户端版本为8.0时请执行以下命令：
     ```
     mysqldump -h {DB_ADDRESS} -P {DB_PORT} -u {DB_USER} -p --single-transaction --hex-blob --complete-insert --set-gtid-purged=OFF --quick --no-create-info --skip-comments  --skip-add-locks --add-locks=false --column-statistics=0 --skip-tz-utc [--where=""] {DB_NAME}{TABLE_NAME} > {mysql_table_data.sql}
     ```
     
   
   
   ![](https://support.huaweicloud.com/usermanual-ddm/public_sys-resources/note_3.0-zh-cn.png)
   如果自建MySQL中有多个逻辑库，建议分开多次执行该命令导出表数据。
   相关参数解释如[表3]所示。
    表3参数解释 
   | 参数                    | 说明                                                                               | 备注                                                                                                              |
   |:---|:---|:---|
   | DB_ADDRESS            | 待导出数据的数据库连接地址。                                                                   | 必填                                                                                                              |
   | DB_PORT               | 数据库侦听端口                                                                          | 必填                                                                                                              |
   | DB_USER               | 数据库用户                                                                            | 必填                                                                                                              |
   | --complete-insert     | 使用完整的insert语句(包含列名称)。                                                            | -                                                                                                               |
   | --single-transaction  | 该选项在导出数据之前提交一个BEGIN SQL语句，BEGIN 不会阻塞任何应用程序且能保证导出时数据库的一致性状态。它只适用于多版本存储引擎，仅InnoDB。 | -                                                                                                               |
   | --quick               | 不缓冲查询，直接导出到标准输出。                                                                 | 避免大数据情况内存暴涨。                                                                                                    |
   | --hex-blob            | 使用十六进制格式导出二进制字符串字段。如果有二进制数据就必须使用该选项。                                             | -                                                                                                               |
   | --no-create-info      | 只导出数据，而不添加CREATE TABLE 语句。                                                       | 导出数据时使用。                                                                                                        |
   | --skip-comments       | 关闭附加注释信息。                                                                        | -                                                                                                               |
   | --add-locks=false     | 导出的数据文件中不加锁表的声明。                                                                 | -                                                                                                               |
   | --set-gtid-purged=OFF | 如果使用的MySQL版本为8.0或5.7，则需要配置该参数。                                                   | 如果使用的MySQL版本为5.6或低于5.6，则不需要配置该参数。                                                                               |
   | --skip-add-locks      | 在导出数据时，控制加锁动作，以避免因耗能引起的性能问题。                                                     | -                                                                                                               |
   | --where               | 只转储给定的WHERE条件选择的记录。                                                              | 如果条件包含命令解释符专用空格或字符，一定要将条件引用起来。                                                                                  |
   | DB_NAME               | 数据库名称                                                                            | 必填                                                                                                              |
   | TABLE_NAME            | 表名                                                                               | 可以多个同类型的表，用空格隔开。 建议只导出与业务相关的表结构。                                                 |
   | mysql_table_data.sql  | 生成的表数据文件名。                                                                       | 每次导出不同表时文件名不同。 建议以"逻辑库名"+"_"+"逻辑表名"+"_"+"data"格式命名，以免数据被覆盖。如mysql_table_data.sql。 |
      
   ![](https://support.huaweicloud.com/usermanual-ddm/public_sys-resources/note_3.0-zh-cn.png)
   - 此处举例的参数为数据导出中常用的参数，由于mysqldump参数无法逐一列举，如果存在个别参数调优等特殊情况，请在MySQL官网查询。
   
   - 使用mysqldump工具进行转移MySQL数据时，请保持MySQL客户端版本和DDM所支持的MySQL版本一致。如果版本不一致，可能会影响数据导出性能。
    
   
   
3. 查看导出SQL文本文件的大小，验证导出数据是否成功。 
   - 如大小不为0字节，说明导出成功。
   
   - 如大小为0字节，说明导出失败，请在管理控制台右上角，选择"工单 \> 新建工单"，联系DDM客服人员。
   
   
   
   
4. 将导出的SQL数据文件上传至已准备的ECS。
 
#### 导入数据
1. 开启应用程序访问DDM数据库只读开关。
2. 清理目标DDM实例的测试数据，防止和待迁移数据冲突。
3. 如果是单表或普通表，采用MySQL客户端直连DDM实例，直接执行以下命令导入表结构文本文件和数据文件。 
   ```
   mysql -f -h {DDM_ADDRESS} -P {DDM_PORT} -u {DDM_USER} -p {DB_NAME} < {mysql_table_schema.sql}
   Enter password: **********
   mysql -f -h {DDM_ADDRESS} -P {DDM_PORT} -u {DDM_USER} -p {DB_NAME} < {mysql_table_data.sql}
   Enter password: **********
   ```
   - DDM_ADDRESS为待导入数据的DDM实例的地址。
   
   - DDM_PORT为DDM实例的端口*。*
   
   - DDM_USER为DDM实例的用户名。
   
   - DB_NAME为DDM逻辑库名称，如果导入的是单表，DB_NAME为DDM实例第一个分片的物理数据库。
   
   - mysql_table_schema.sql为待导入的表结构文件名。
   
   - mysql_table_data.sql为待导入的表数据文件名。
     ![](https://support.huaweicloud.com/usermanual-ddm/public_sys-resources/note_3.0-zh-cn.png)
     单表或普通表导入前，需要编辑表结构文本文件，将最后一行信息删除（Dump completed on 2018-06-28 19:53:03），否则可能导致无法导入。
     
   
   
   
   
4. 如果是拆分表或广播表，采用MySQL客户端连接DDM将数据文件导入。 
   ```
   mysql -h {DDM_ADDRESS} -P {DDM_PORT} -u {DDM_USER} -p {DB_NAME} < {mysql_table_data.sql}
   Enter password: **********
   ```
   - DDM_ADDRESS为待导入数据的DDM的地址。
   
   - DDM_PORT为DDM侦听端口*。*
   
   - DDM_USER为DDM用户。
   
   - DB_NAME为DDM逻辑库名称。
   
   - mysql_table_data.sql为待导入的表数据文件名。
     ![](https://support.huaweicloud.com/usermanual-ddm/public_sys-resources/notice_3.0-zh-cn.png)
     - 数据导入阶段会在一定程度上影响DDM实例以及RDS for MySQL实例性能，请选择在业务低峰时间导入。
     
     - 如果导入过程中出现中断或异常，为防止表数据主键冲突可以用SQL语句**truncate table** ***{TABLE_NAME}***清空再重新导入。该命令属于高危操作，执行后会清空表中所有数据，请谨慎使用。
     
     - 请勿把数据量大（超过500万）的数据导入到广播表。
       
   
   
   
   
 
#### 数据验证
1. 在ECS上对DDM实例进行逻辑备份。 
   - 导出表结构：
     - MySQL客户端版本为5.6时请执行以下命令：
       ```
       mysqldump -h {DDM_ADDRESS} -P {DDM_PORT} -u {DDM_USER} -p --skip-lock-tables --default-auth=mysql_native_password  --set-gtid-purged=OFF --skip-tz-utc --no-data {DB_NAME} {TABLE_NAME} > {mysql_table_schema_new.sql}
       ```
       
     
     - MySQL客户端版本为8.0时请执行以下命令：
       ```
       mysqldump -h {DDM_ADDRESS} -P {DDM_PORT} -u {DDM_USER} -p --skip-lock-tables --default-auth=mysql_native_password --column-statistics=0 --set-gtid-purged=OFF --skip-tz-utc --no-data {DB_NAME} {TABLE_NAME} > {mysql_table_schema_new.sql}
       ```
       
      
   
   - 导出表数据：
     - MySQL客户端版本为5.6时请执行以下命令：
       ```
       mysqldump -h {DDM_ADDRESS} -P {DDM_PORT} -u {DDM_USER} -p --single-transaction --hex-blob --complete-insert --set-gtid-purged=OFF --quick --no-create-info --skip-comments --skip-tz-utc [--where=""] {DB_NAME}{TABLE_NAME} > {mysql_table_data_new.sql}
       ```
       
     
     - MySQL客户端版本为8.0时请执行以下命令：
       ```
       mysqldump -h {DDM_ADDRESS} -P {DDM_PORT} -u {DDM_USER} -p --single-transaction --hex-blob --complete-insert --set-gtid-purged=OFF --quick --no-create-info --skip-comments --column-statistics=0 --skip-tz-utc [--where=""] {DB_NAME}{TABLE_NAME} > {mysql_table_data_new.sql}
       ```
       
      
   
   
   
   
2. 检查数据一致性。 
   1. 在自建MySQL和DDM实例执行如下SQL语句检查每张表的记录数是否相等。其中TABLE_NAME是表名。
      ```
      select count(*) from {TABLE_NAME};
      ```
      
   
   2. 在ECS上对导出前后的表结构和表数据进行比较。
      ```
      diff -B -w -q -i {mysql_table_schema.sql} {mysql_table_schema_new.sql};echo $?
      diff -B -w -q -i {mysql_table_data.sql} {mysql_table_data_new.sql};echo $?
      ```
      ![](https://support.huaweicloud.com/usermanual-ddm/public_sys-resources/note_3.0-zh-cn.png)
      - 表结构的导出命令只适用于单表和普通表。
      
      - 如果导出数据的顺序不一致，无法比较。
       
      - 如果导入前后相同，则表示数据迁移成功。
      
      - 如果数据存在差异，请在管理控制台右上角，选择"工单 \> 新建工单"，联系DDM客服人员进行定位。
       
   
   
   
   
3. 端到端验证应用程序通过DDM实例访问相关表只读功能是否正常。
4. 关闭应用程序访问DDM数据库只读开关。
 
#### 业务验证
1. 切换业务数据源至DDM。
2. 验证是否能正常读取、写入数据。
   - 正常：完成迁移。
   
   - 异常：切换业务数据源至自建MySQL，请在管理控制台右上角，选择"工单 \> 新建工单"，联系DDM管理人员进行定位。
    
 
