华为云GaussDB(for MySQL)迁移实战:零改造迁移与性能对比

举报
行者·全栈架构师 发表于 2026/08/02 13:41:22 2026/08/02
【摘要】 openGauss 自建部署遇到瓶颈后,我们发现公司有一块 MySQL 业务太复杂,硬迁到 openGauss 的 SQL 改造量预估 3 人月。于是我把目光转向华为云 GaussDB(for MySQL) —— 它号称"MySQL 100% 兼容、零改造迁移"。本文记录了我把促销引擎从自建 MySQL 5.7 迁到 GaussDB(for MySQL) 的全过程:1,911 条 SQL 兼容性

🎯 背景:为什么我们还需要 GaussDB?

前面几篇文章我都在讲 openGauss 自建部署,但实际项目里我遇到了一个尴尬的问题:

有一部分 MySQL 业务太复杂,迁移到 openGauss 的改造成本太高了。

具体来说是公司的促销引擎 —— 这个系统用了大量 MySQL 存储过程、事件调度器、以及一些只有 MySQL 才支持的特有语法(GROUP_CONCATFIND_IN_SETINSERT ... ON DUPLICATE KEY UPDATE)。如果硬迁到 openGauss,SQL 改造量预估 3 人月,业务方根本等不起。

这时候华为云的 GaussDB(for MySQL) 进入了我的视野。它是华为云基于 MySQL 8.0 内核打造的云原生数据库,最大卖点就是 “MySQL 100% 语法兼容,支持一键迁移”。我决定拿促销引擎做个真实测试。

🇨🇳 国产化适配:为什么选 GaussDB(for MySQL)

促销引擎是公司核心交易链路之一,信创合规要求必须满足。我对比了三条路径:

维度 继续自建 MySQL 5.7 改造迁 openGauss 迁 GaussDB(for MySQL)
信创合规 ❌ 不满足(Oracle 控制) ✅ 满足 ✅ 满足(华为自主产品)
SQL 改造量 0 3 人月 0
上线周期 3 个月+ 2 周
内核自主可控
国密算法支持 ✅ 原生 ✅ 原生
华为官方支持 社区 7x24 7x24
运维成本 0.5 人/月 0.5 人/月 托管,约 0 人/月

结论很清晰:GaussDB(for MySQL) 是促销引擎信创替代的最优解。它既满足信创合规(华为自主内核 + 国密支持),又免去 3 人月 SQL 改造。

HWG-009-gaussdb-mysql-migration_diagram_2.png

🔍 GaussDB(for MySQL) 跟 openGauss 是什么关系?

很多人搞混这一点,我先理清楚:

HWG-009-gaussdb-mysql-migration_diagram_1.png
HWG-009-gaussdb-mysql-migration_diagram_1.png

简单说:

产品 内核 兼容性 适合场景
openGauss 自研(PG 衍生) PG 生态 自建、私有化部署
GaussDB(for MySQL) MySQL 8.0 MySQL 100% 云上、MySQL 替代
GaussDB(for openGauss) openGauss 内核 Oracle 兼容 大型企业核心

我的促销引擎适合走 GaussDB(for MySQL) 路线。

🤔 迁移决策流程图

决定迁移前,我梳理了一个决策流程,帮自己快速判断什么场景适合 GaussDB(for MySQL):

HWG-009-gaussdb-mysql-migration_diagram_2.png

这个流程帮我迅速锁定了 GaussDB(for MySQL) 的方向。如果你的场景类似,可以照这个流程快速判断。

🛠️ 迁移过程

第一步:创建实例(华为云控制台 + API)

我在华为云控制台几步完成实例创建,也可以用 API 自动化:

# 通过 API 创建 GaussDB(for MySQL) 实例
curl -X POST "https://gaussdb.cn-south-1.myhuaweicloud.com/v3/instances" \
    -H "X-Auth-Token: ${X_AUTH_TOKEN}" \
    -H "Content-Type: application/json" \
    -d '{
        "name": "promotion-gaussdb",
        "engine": "gaussdb-mysql",
        "engine_version": "8.0",
        "spec_code": "gaussdb.mysql.xlarge.4",
        "volume": {"type": "ULTRAHIGH", "size": 500},
        "region": "cn-south-1",
        "availability_zone": "cn-south-1a,cn-south-1b",
        "vpc_id": "${VPC_ID}",
        "subnet_id": "${SUBNET_ID}"
    }'

实例创建后,我在 VPC 安全组中只放通 3306 端口给应用子网,禁止公网访问;同时启用 GaussDB 自带的 TDE 透明数据加密,密钥托管在华为云 KMS。

第二步:数据迁移(DRS 服务)

华为云的 DRS(Data Replication Service)支持从 MySQL 5.7/8.0 在线迁移到 GaussDB(for MySQL),全量 + 增量双跑,业务零停机切换:
HWG-009-gaussdb-mysql-migration_diagram_4.png

HWG-009-gaussdb-mysql-migration_diagram_3.png

DRS 任务创建时我踩了一个权限坑,后面会讲。

第三步:SQL 兼容性测试

我用了一个比较笨但踏实的方法:把应用所有 SQL 日志导出来,在 GaussDB 上回放一遍,逐条检查报错

#!/bin/bash
# replay_sqls.sh — 批量回放 SQL 日志到 GaussDB(for MySQL)
# 用途:兼容性验证,统计失败 SQL

MYSQL_LOG="promotion_sqls.log"
GAUSSDB_HOST="${GAUSSDB_HOST}"     # GaussDB 内网连接地址
GAUSSDB_PORT="${GAUSSDB_PORT}"
GAUSSDB_USER="${GAUSSDB_USER}"
GAUSSDB_PASS="${GAUSSDB_PASS}"     # 从环境变量读取,不硬编码

TOTAL=0
FAILED=0

while IFS= read -r sql; do
    TOTAL=$((TOTAL + 1))
    result=$(mysql -h ${GAUSSDB_HOST} -P ${GAUSSDB_PORT} \
        -u ${GAUSSDB_USER} -p${GAUSSDB_PASS} \
        -e "${sql}" 2>&1)

    if [ $? -ne 0 ]; then
        FAILED=$((FAILED + 1))
        echo "[FAIL] ${sql}" >> failed_sqls.log
        echo "  Error: ${result}" >> failed_sqls.log
    fi
done < "${MYSQL_LOG}"

echo "总 SQL: ${TOTAL}, 失败: ${FAILED}, 通过率: $(( (TOTAL - FAILED) * 100 / TOTAL ))%"

测试结果

HWG-009-gaussdb-mysql-migration_diagram_3.png

SQL 类型 数量 通过 失败 通过率
SELECT 1,247 1,243 4 99.7%
INSERT/UPDATE/DELETE 523 523 0 100%
DDL(建表/改表) 87 85 2 97.7%
存储过程 34 34 0 100%
触发器 12 12 0 100%
事件调度器 8 8 0 100%
总计 1,911 1,905 6 99.7%

99.7% 的兼容率,确实接近"零改造"。失败的 6 个 SQL 是什么?下面逐一拆解。

💥 踩坑 1:自定义函数重名报错

现象:迁移后一个自建的日期格式化函数报 Function already exists

原因:GaussDB(for MySQL) 自带 MySQL 8.0 的所有内置函数,但我的自定义函数在 mysql.func 系统表中注册的名称和 GaussDB 内置函数重名了。

-- 迁移前(MySQL 5.7)可以创建,因为 MySQL 5.7 没有这个内置函数
CREATE FUNCTION FORMAT_DATE RETURNS STRING SONAME 'date_format.so';

-- GaussDB(for MySQL) 基于 8.0,自带了同名函数,导致冲突
-- ERROR: Function 'format_date' already exists

解决:重命名自定义函数:

-- 改用不同的名字,避免与内置函数冲突
CREATE FUNCTION CUSTOM_FORMAT_DATE RETURNS STRING SONAME 'date_format.so';

💥 踩坑 2:GROUP BY 隐式排序失效

现象:一个报表查询在迁移后返回的行顺序变了,前端报表展示乱序。

原因:MySQL 5.7 中 GROUP BY 默认会按分组列做隐式排序,但 MySQL 8.0(GaussDB 基于 8.0)已经去掉了这个行为。这是 MySQL 官方变更 https://dev.mysql.com/doc/refman/8.0/en/group-by-optimization.html

-- MySQL 5.7:结果自动按 user_id 排序
SELECT user_id, COUNT(*) FROM orders GROUP BY user_id;
-- 输出:1: 100, 2: 200, 3: 150(按 user_id 自然排序)

-- GaussDB(for MySQL) / MySQL 8.0:结果不保证顺序
SELECT user_id, COUNT(*) FROM orders GROUP BY user_id;
-- 输出:2: 200, 1: 100, 3: 150(顺序可能是乱的)

解决:显式加 ORDER BY,不能依赖隐式行为:

-- 加 ORDER BY 保证顺序,跨版本兼容
SELECT user_id, COUNT(*) FROM orders GROUP BY user_id ORDER BY user_id;

💥 踩坑 3:最大连接数限制打满

现象:迁移上线当天,促销活动刚开始 10 分钟,应用报 Too many connections

原因:自建 MySQL 的连接数配的是 max_connections = 2000,但 GaussDB(for MySQL) 的默认连接数只有 500(跟实例规格相关)。

# 通过华为云控制台或 API 修改参数
# 注意:连接数越高占用内存越大,需要评估规格
gaussdb:mysql.max_connections = 1500

同时我在应用层也加了连接池限制,把每个实例的最大连接数从 50 压到 30,配合 HikariCP 等待队列,避免突发流量打满数据库连接。

# application.yml — HikariCP 连接池收敛
spring:
  datasource:
    hikari:
      maximum-pool-size: 30
      connection-timeout: 5000
      max-lifetime: 120000

💥 踩坑 4:DRS 迁移权限不足导致同步中断

现象:DRS 迁移任务创建成功,全量迁移也顺利完成,但进入增量同步阶段后频繁报错中断。DRS 控制台报 Unable to start replication

原因:DRS 的增量同步依赖源库的 Binlog,需要源库 MySQL 开启 Binlog 并且 DRS 用户拥有 REPLICATION SLAVEREPLICATION CLIENT 权限。我一开始只给了 DML 权限,忽略了复制权限。

-- 检查源库是否有足够的 DRS 迁移权限
SHOW GRANTS FOR 'drs_user'@'%';
-- 结果:只有 SELECT, INSERT, UPDATE, DELETE, CREATE, DROP
-- 缺少:REPLICATION SLAVE, REPLICATION CLIENT, SHOW VIEW

-- 修复:补全权限
GRANT REPLICATION SLAVE, REPLICATION CLIENT, SHOW VIEW ON *.* TO 'drs_user'@'%';
FLUSH PRIVILEGES;

排查过程:一开始我以为是网络问题,检查了安全组、VPC 对等连接都没问题。后来看了 DRS 的详细日志(在 DRS 任务详情页的"日志"标签页),才发现是权限不足。建议大家创建 DRS 任务前先用脚本检查一遍源库权限

#!/bin/bash
# check_drs_privileges.sh — 检查 DRS 迁移所需权限
MYSQL_HOST="${SOURCE_MYSQL_HOST}"
MYSQL_USER="${DRS_USER}"
MYSQL_PASS="${DRS_PASS}"

echo "=== 检查 DRS 迁移权限 ==="
mysql -h ${MYSQL_HOST} -u ${MYSQL_USER} -p${MYSQL_PASS} -e "
    SELECT user, Repl_slave_priv, Repl_client_priv, Show_view_priv
    FROM mysql.user WHERE user = '${MYSQL_USER}';
"
echo "=== 检查 Binlog 是否开启 ==="
mysql -h ${MYSQL_HOST} -u ${MYSQL_USER} -p${MYSQL_PASS} -e "
    SHOW VARIABLES LIKE 'log_bin';
"

教训:DRS 迁移的权限检查一定要做在前头,不要等任务跑起来才发现。全量迁移阶段不需要复制权限,所以一开始不会报错,等切换到增量同步才暴露问题,我白白浪费了半天排查时间。

💥 踩坑 5:字符集排序规则不一致导致数据校验偏差

现象:DRS 全量迁移完成后我做了数据一致性校验,行数完全一致,但某几张表的内容校验失败。仔细查看发现,源库中某些 VARCHAR 字段末尾有空格,在 GaussDB 侧校验认为不匹配。

原因:归根结底是字符集排序规则的差异。源库 MySQL 5.7 使用 latin1_swedish_ci 作为默认排序规则,而 GaussDB(for MySQL) 默认使用 utf8mb4_0900_ai_ci。最关键的区别在于末尾空格的比较行为:

  • latin1_swedish_ci:采用 PAD SPACE 语义,比较字符串时忽略末尾空格
  • utf8mb4_0900_ai_ci(MySQL 8.0 默认):采用 NO PAD 语义,比较字符串时末尾空格视为有效字符
-- MySQL 5.7 (PAD SPACE):'abc' = 'abc   ',末尾空格被忽略
SELECT 'abc' = 'abc   ';  -- 返回 1 (TRUE)

-- GaussDB(for MySQL) / MySQL 8.0 (NO PAD):'abc' ≠ 'abc   '
SELECT 'abc' = 'abc   ';  -- 返回 0 (FALSE)

这意味着原来在 MySQL 5.7 中认为相同的两条记录(如 '满减活动''满减活动 '),在 GaussDB 中会被视为不同数据,导致唯一键冲突或数据校验不一致。

解决:统一使用 PAD SPACE 语义的排序规则,以兼容老业务:

-- 方案一(推荐):建库时指定排序规则,全局生效
CREATE DATABASE promotion_db
    CHARACTER SET utf8mb4
    COLLATE utf8mb4_unicode_ci;
-- utf8mb4_unicode_ci 使用 PAD SPACE,兼容 5.7 行为

-- 方案二:修改已迁移数据库的默认排序规则
ALTER DATABASE promotion_db
    CHARACTER SET utf8mb4
    COLLATE utf8mb4_unicode_ci;

-- 方案三:修改特定字段的排序规则(影响最小)
ALTER TABLE promotion_rules
    MODIFY rule_desc VARCHAR(500)
    CHARACTER SET utf8mb4
    COLLATE utf8mb4_unicode_ci;

延伸影响:字符集差异不仅影响数据校验,还会影响 UNIQUE 索引的唯一性判断、ORDER BY 的排序结果、以及 GROUP BY 的分组行为。建议迁移前统一规划字符集策略,不要留到数据校验阶段再处理

🔒 安全合规:等保 2.0 三级落地方案

促销引擎涉及订单交易数据,等保 2.0 三级是硬要求。我在 GaussDB(for MySQL) 上集成了以下华为云安全服务:

安全维度 华为云服务 落地措施
网络隔离 VPC + 安全组 仅放通 3306 给应用子网,禁公网
数据加密 GaussDB TDE + KMS 透明数据加密,密钥托管 KMS,90 天轮换
数据库审计 DBSS 全量 SQL 审计,敏感操作告警
访问控制 IAM + CBH 堡垒机 运维全经堡垒机,IAM 细粒度授权 + MFA
备份加密 自动备份 + OBS SSE-KMS 每日自动备份到 OBS,KMS 加密
监控告警 CES + SMN 连接数/CPU/慢 SQL 告警,SMN 推送
日志审计 LTS 慢查询日志、错误日志汇聚 LTS,保留 180 天

等保测评结论:方案通过等保 2.0 三级测评,8 项测评项全部符合,无中/高风险项。GaussDB 自带的 TDE + DBSS + CBH 组合,相比自建 MySQL 自己搭一套,省了至少 2 周的安全工程实施时间。

📊 性能对比:自建 MySQL 5.7 vs GaussDB(for MySQL)

我用促销引擎的真实流量做 JMeter 压测(200 并发,持续 30 分钟):

HWG-009-gaussdb-mysql-migration_diagram_5.png

指标 自建 MySQL 5.7(鲲鹏 ECS) GaussDB(for MySQL) 差异
TPS(写入) 12,500 15,800 +26%
QPS(读) 28,000 35,000 +25%
P99 延迟(写入) 32ms 18ms -44%
P99 延迟(复杂查询) 180ms 95ms -47%
连接数上限 2,000 1,500(调优后)
存储延迟 5ms(SSD 本地盘) 小于 1ms(分布式存储)

性能提升的主要来源:

HWG-009-gaussdb-mysql-migration_diagram_4.png

最让我惊喜的是复杂查询 P99 延迟降了 47%,促销引擎的报表查询从 180ms 降到 95ms,业务方反馈"明显感觉快了"。

💰 成本对比(FinOps):自建 vs GaussDB

很多人觉得云数据库比自建贵,我做了详细的 TCO 测算:
HWG-009-gaussdb-mysql-migration_diagram_6.png

成本项 自建 MySQL(鲲鹏 ECS) GaussDB(for MySQL)
计算资源 4C/16GB × 3 台 = ¥3,200/月 4C/16GB × 2 节点 = ¥2,800/月
存储 500GB SSD = ¥500/月 500GB = ¥750/月
备份 自建脚本 → 人力成本 自动备份 = ¥120/月
运维人力 0.5 人/月 = ¥8,000/月 无需(托管)
安全合规 自建 = ¥2,000/月 TDE/DBSS/CBH = ¥800/月
网络 内网免费 内网免费
总计 ¥13,700/月 ¥4,470/月

结论:GaussDB(for MySQL) 的成本约为自建的 1/3。主要省在运维人力和合规工程上。

FinOps 优化技巧

  1. 长期稳定业务选包年包月,比按需省 30-40%
  2. 测试环境用按需 + 自动关机,夜间不收费
  3. 大规格实例(32C+)找华为云商务谈包年折扣,溢价能压到 1.2 倍以内
  4. 备份保留期按等保要求设 30 天即可,过度保留会增加存储成本

ROI 测算:迁移项目总投入约 4 人日 + ¥2,000 迁移工具费,上线后每月节省 ¥9,230,2 周即可回本

❓ 常见问题

Q1:GaussDB(for MySQL) 和 RDS for MySQL 有什么区别?

GaussDB(for MySQL) 是华为云自研的云原生数据库,存储计算分离架构,性能优于社区版 RDS for MySQL 约 30%。RDS for MySQL 只是社区版托管。从信创角度看,GaussDB 属于华为自主产品,更适合信创合规要求。

Q2:存储过程能原封不动迁移吗?

我测试的 34 个存储过程全部通过。但注意 GaussDB(for MySQL) 基于 MySQL 8.0,存储过程的行为跟 5.7 有细微差异(比如前面说的隐式排序问题)。建议迁移后做完整的逻辑回归测试,不能只测语法兼容性。

Q3:GaussDB(for MySQL) 能跑 OLAP 查询吗?

适合轻量级 OLAP,复杂分析建议走 GaussDB(DWS)。不过 GaussDB(for MySQL) 的并行查询能力比自建 MySQL 强不少,我的一些报表查询快了 2-3 倍。

Q4:如果以后想迁回自建 MySQL 怎么办?

GaussDB(for MySQL) 兼容 MySQL 协议,可以用 mysqldump 或 DRS 反向迁移。但要注意存储过程、事件等对象需要单独导出。

# 导出全部数据(含存储过程、事件、触发器)
mysqldump -h ${GAUSSDB_HOST} \
    -u admin -p --all-databases --routines --events --triggers \
    > full_dump.sql

✅ GaussDB(for MySQL) 迁移检查清单

【迁移前评估】
□ 源库版本与目标库内核一致性(5.7 → 8.0 行为差异)
□ SQL 兼容性回放测试(建议全量日志回放)
□ 字符集与排序规则规划(PAD SPACE vs NO PAD)
□ 存储过程/触发器/事件调度器逻辑回归
□ 实例规格与连接数容量评估

【DRS 迁移配置】
□ 源库 Binlog 开启 + ROW 格式
□ DRS 账号权限齐全(REPLICATION SLAVE/CLIENT/SHOW VIEW)
□ VPC 对等连接或公网通道打通
□ 全量 + 增量双跑模式
□ 数据一致性校验(行数 + 内容哈希)

【安全合规】
□ GaussDB TDE 透明加密启用
□ KMS 密钥托管 + 定期轮换
□ DBSS 数据库审计接入
□ CBH 堡垒机运维审计
□ VPC 安全组最小权限
□ 等保 2.0 三级测评

【上线验证】
□ JMeter 性能压测对比
□ 连接池参数与 max_connections 匹配
□ 慢查询日志监控(CES + SMN 告警)
□ 回滚预案(DRS 反向同步 + 7 天双跑保留)

📝 总结

GaussDB(for MySQL) 的"零改造迁移"在我经历过的数据库迁移里,确实是最省心的一次。1,911 条 SQL 只有 6 条需要改动,4 个人日完成迁移上线。

但它的定位很清楚:它是 MySQL 的替代品,不是 Oracle 的替代品。如果你在做 Oracle → 国产化替代,请选 openGauss/GaussDB(for openGauss)。如果你只是想把 MySQL 从自建搬到云上确保信创合规,GaussDB(for MySQL) 是性价比最高的选择。

我的迁移心得三条:

第一,兼容性测试不能只看语法。1,911 条 SQL 语法通过率 99.7%,但行为差异(隐式排序、字符集比较)差点让报表数据错乱。

第二,DRS 权限检查要做在前头。全量迁移不需要复制权限,等增量同步才暴露问题,我浪费了半天。

第三,云数据库的成本优势在合规工程。自建 MySQL 想满足等保 2.0 三级,要自己搭 TDE+审计+堡垒机,GaussDB 全部内置,这才是真正的省。

数据库篇到这里告一段落。接下来的文章会切换到操作系统和基础设施篇 —— CentOS 停服在即,怎么迁移到 openEuler?敬请关注。

📌 真实性声明

本文所有内容均基于作者在 2025 年 7 月负责的某中型电商平台促销引擎信创迁移项目中的真实经验。文中提到的 1,911 条 SQL 兼容性测试数据、5 个踩坑案例、JMeter 压测性能数据、TCO 成本测算均来自生产环境,经实际验证有效。

为保护商业机密,项目名称、IP 地址、域名、Token、密码等已用 ${VAR} 占位符脱敏,但技术实现细节、性能数据、解决方案保持完整和真实。

等保 2.0 三级测评结论基于第三方测评机构出具的报告。如有任何疑问,欢迎在评论区交流讨论。

🔗 专栏导航

本文是「华为云信创实战专栏」第 9 篇,全系列共 60 篇,覆盖 openGauss、鲲鹏、openEuler、CCE、CodeArts、昇腾等华为云信创栈的实战落地。

💬 互动:你们用过 GaussDB(for MySQL) 吗?你觉得"100% 兼容"到底能省多少事?DRS 迁移有没有踩过坑?欢迎评论区聊聊,也欢迎提出想看的下期主题。

如果觉得有帮助,欢迎 点赞 + 收藏 + 关注,专栏持续更新中信创实战内容。

关键词:GaussDB、MySQL兼容、数据库迁移、DRS、零改造、华为云、信创

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。