迁移实战:CentOS+MySQL+Redis → 麒麟+达梦+TongRDS

📅 2026/8/21 18:45:04
迁移实战:CentOS+MySQL+Redis → 麒麟+达梦+TongRDS
第 9 章 迁移实战CentOSMySQLRedis → 麒麟达梦TongRDS9.1 迁移全景图6 步走[原环境] [目标环境] CentOS 7.9 → 麒麟 V10 SP3 MySQL 5.7 → 达梦 DM8 Redis 6.2 → TongRDS东方通国产 Redis Nginx 1.20 → Nginx重编译链接国密 SSL PHP 7.4 → PHP 8.3重编译支持达梦迁移周期3 台服务器规模15 个工作日第 1-3 天环境准备装系统、编译软件第 4-7 天数据库迁移MySQL → 达梦SQL 改造第 8-10 天应用改造代码适配达梦、Redis 接口兼容第 11-12 天测试验证功能测试 压测第 13-14 天灰度上线10% 流量验证第 15 天全量切换 回滚预案9.2 第一步环境准备麒麟 V10 初始化9.2.1 系统安装三台服务器# 服务器规划# 192.168.1.101 app-server-1 (Web PHP-FPM)# 192.168.1.102 app-server-2 (Web PHP-FPM)# 192.168.1.103 db-server (达梦 DM8 TongRDS)# 麒麟 V10 安装完成后第一件事换源用麒麟官方或清华镜像sudotee/etc/yum.repos.d/kylin.repo/dev/nullEOF [kylin-os] nameKylin Linux Advanced Server 10 - os baseurlhttp://update.cs2c.com.cn/NS/V10/V10SP3/os/$basearch/ enabled1 gpgcheck0 EOFsudoyum clean allsudoyum makecache9.2.2 基础优化照抄第 2 章核心三步# 1. 关闭 SELinux测试环境sudosetenforce0sudosed-is/^SELINUXenforcing/SELINUXdisabled//etc/selinux/config# 2. 提升文件描述符echo* soft nofile 65535|sudotee-a/etc/security/limits.confecho* hard nofile 65535|sudotee-a/etc/security/limits.conf# 3. 内核参数sudotee-a/etc/sysctl.conf/dev/nullEOF kernel.shmmax 2147483648 kernel.shmall 524288 net.core.somaxconn 8192 net.ipv4.tcp_max_syn_backlog 8192 net.ipv4.ip_local_port_range 1024 65535 net.ipv4.tcp_tw_reuse 1 net.ipv4.tcp_fin_timeout 15 EOFsudosysctl-p9.3 第二步达梦数据库安装与初始化9.3.1 安装达梦 DM8db-server 上# 1. 下载达梦安装包需要官网注册假设已下载到 /tmp/dm8_setup.tarcd/tmptar-xfdm8_setup.tarcddm8_setup# 2. 图形化安装需要 X11 转发或静默安装# 静默安装示例推荐可自动化./DMInstall.bin-isilent\INSTALL_PATH/opt/dmdbms\DM_USERdmdba\DM_GROUPdmdba\DM_PWDDameng123# 3. 创建数据库实例su- dmdbacd/opt/dmdbms/bin ./dminitpath/data/dmdatapage_size16\extent_size16case_sensitivencharset1# charset1 是 UTF-8# 4. 注册为 systemd 服务sudotee/etc/systemd/system/dm8.service/dev/nullEOF [Unit] DescriptionDM Database Server Afternetwork.target [Service] Typeforking Userdmdba Groupdmdba ExecStart/opt/dmdbms/bin/dmserver /data/dmdata/DAMENG/dm.ini ExecStop/opt/dmdbms/bin/dmserver /data/dmdata/DAMENG/dm.ini stop Restarton-failure [Install] WantedBymulti-user.target EOFsudosystemctl daemon-reloadsudosystemctlenabledm8sudosystemctl start dm8# 5. 验证/opt/dmdbms/bin/disql SYSDBA/SYSDBAlocalhost:5236# 进入 SQL 提示符后输入SELECT * FROM V$VERSION;9.3.2 创建业务库和用户-- 在 disql 里执行CREATEUSERmyapp IDENTIFIEDBYMyApp2024;GRANTDBATOmyapp;-- 生产环境不要给 DBA按需授权-- 创建业务表空间可选性能优化用CREATETABLESPACEmyapp_data DATAFILE/data/dmdata/myapp_data01.dbfSIZE1024AUTOEXTENDONNEXT128;ALTERUSERmyappDEFAULTTABLESPACEmyapp_data;9.4 第三步MySQL 数据迁移到达梦9.4.1 导出 MySQL 数据原 CentOS 服务器上# 导出结构 数据分开导方便改表结构mysqldump-h127.0.0.1-uroot-p\--no-data\--skip-add-drop-table\--databasesmyapp/tmp/myapp_schema.sql mysqldump-h127.0.0.1-uroot-p\--no-create-info\--skip-extended-insert\--databasesmyapp/tmp/myapp_data.sql# 拷贝到达梦服务器scp/tmp/myapp_*.sql dmdba192.168.1.103:/tmp/9.4.2 SQL 改造MySQL → 达梦语法自动转换脚本Python#!/usr/bin/env python3# 文件名mysql2dm.py# 用途把 MySQL 的 DDL 转成达梦兼容的 SQLimportreimportsysdefconvert_schema(sql):# 1. 表名/字段名加双引号达梦大小写敏感sqlre.sub(rCREATE TABLE (\w),rCREATE TABLE \1,sql)sqlre.sub(r(\w),r\1,sql)# 2. AUTO_INCREMENT → IDENTITYsqlre.sub(r(\w)\sINT.*AUTO_INCREMENT,r\1 INT IDENTITY(1,1),sql)sqlre.sub(r(\w)\sBIGINT.*AUTO_INCREMENT,r\1 BIGINT IDENTITY(1,1),sql)# 3. 类型转换sqlre.sub(rTINYINT\(1\),TINYINT,sql)# 达梦的 TINYINT 就是布尔sqlre.sub(rDATETIME,TIMESTAMP,sql)sqlre.sub(rTEXT,CLOB,sql)sqlre.sub(rLONGTEXT,CLOB,sql)sqlre.sub(rBLOB,BLOB,sql)# 4. 索引语法MySQL 的 KEY 改成 INDEXsqlre.sub(r\sKEY\s, INDEX ,sql)# 5. 字符集和排序规则达梦不需要sqlre.sub(rCHARACTER SET \w,,sql)sqlre.sub(rCOLLATE \w,,sql)sqlre.sub(rENGINE\w,,sql)sqlre.sub(rDEFAULT CHARSET\w,,sql)# 6. 注释达梦用 COMMENT ON# 例name VARCHAR(50) COMMENT 姓名# 转成ALTER TABLE users MODIFY name COMMENT 姓名;# 这里简化处理实际要解析整个 CREATE TABLEreturnsqlif__name____main__:withopen(sys.argv[1],r,encodingutf8)asf:sqlf.read()convertedconvert_schema(sql)withopen(sys.argv[1].dm,w,encodingutf8)asf:f.write(converted)print(f转换完成{sys.argv[1]}.dm)运行转换python3 mysql2dm.py /tmp/myapp_schema.sql# 生成 /tmp/myapp_schema.sql.dm手动检查和调整重点-- 原 MySQLCREATETABLEusers(idbigint(20)NOTNULLAUTO_INCREMENT,usernamevarchar(50)NOTNULL,created_atdatetimeDEFAULTCURRENT_TIMESTAMP,PRIMARYKEY(id),UNIQUEKEYidx_username(username))ENGINEInnoDBDEFAULTCHARSETutf8mb4COMMENT用户表;-- 转换后达梦CREATETABLEUSERS(IDBIGINTIDENTITY(1,1)PRIMARYKEY,USERNAMEVARCHAR(50)NOTNULL,CREATED_ATTIMESTAMPDEFAULTSYSDATE,CONSTRAINTUQ_USERNAMEUNIQUE(USERNAME));COMMENTONTABLEUSERSIS用户表;COMMENTONCOLUMNUSERS.IDIS用户ID;COMMENTONCOLUMNUSERS.USERNAMEIS用户名;9.4.3 导入达梦db-server 上# 1. 导入表结构/opt/dmdbms/bin/disql myapp/MyApp2024localhost:5236/tmp/myapp_schema.sql.dm# 2. 检查是否有报错# 常见错误主键重复定义、外键约束语法不兼容# 3. 导入数据转换 INSERT 语句# MySQL 的 INSERT INTO users VALUES (1, alice, 2024-01-01);# 达梦要INSERT INTO USERS VALUES (1, alice, TO_DATE(2024-01-01, YYYY-MM-DD));# 用脚本批量转换正则替换日期格式sed-is/\\([0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\} [0-9]\\{2\\}:[0-9]\\{2\\}:[0-9]\\{2\\}\\)/TO_DATE(\\1, YYYY-MM-DD HH24:MI:SS)/g/tmp/myapp_data.sql /opt/dmdbms/bin/disql myapp/MyApp2024localhost:5236/tmp/myapp_data.sql# 4. 验证数据量disql myapp/MyApp2024localhost:5236EOF SELECT COUNT(*) FROM USERS; SELECT COUNT(*) FROM ORDERS; -- 和 MySQL 原库对比确保一致 EOF9.5 第四步PHP 应用改造MySQL → 达梦驱动9.5.1 数据库配置改造Laravel 示例原.envMySQLDB_CONNECTIONmysql DB_HOST192.168.1.200 DB_PORT3306 DB_DATABASEmyapp DB_USERNAMEroot DB_PASSWORDMyPass123新.env达梦DB_CONNECTIONdm8 DB_HOST192.168.1.103 DB_PORT5236 DB_DATABASEMYAPP DB_USERNAMEmyapp DB_PASSWORDMyApp2024config/database.php加上达梦连接?phpdm8[driverpdo,dsnodbc:DRIVER{DM8 ODBC DRIVER};SERVER.env(DB_HOST).;PORT.env(DB_PORT).;DATABASE.env(DB_DATABASE),usernameenv(DB_USERNAME),passwordenv(DB_PASSWORD),charsetutf8,prefix,options[PDO::ATTR_CASEPDO::CASE_NATURAL,// 保持原始大小写PDO::ATTR_ERRMODEPDO::ERRMODE_EXCEPTION,],],9.5.2 SQL 语句改造代码层改造点 1分页?php// 原代码MySQL$usersDB::table(users)-paginate(10);// 生成 SQLSELECT * FROM users LIMIT 10 OFFSET 0// 改造后达梦兼容$usersDB::table(USERS)-paginate(10);// 达梦的分页语法和 MySQL 一样但表名要大写改造点 2日期函数?php// 原代码MySQL$usersDB::table(users)-where(created_at,,DB::raw(NOW() - INTERVAL 7 DAY))-get();// 改造后达梦$usersDB::table(USERS)-where(CREATED_AT,,DB::raw(SYSDATE - 7))-get();改造点 3字符串拼接?php// 原代码MySQL$resultDB::select(SELECT CONCAT(first_name, , last_name) AS full_name FROM users);// 改造后达梦用 || 或 CONCAT$resultDB::select(SELECT FIRST_NAME || \ \ || LAST_NAME AS FULL_NAME FROM USERS);改造点 4LIMIT 1 优化?php// 原代码MySQL$userDB::table(users)-where(id,1)-limit(1)-first();// 达梦上 LIMIT 1 的性能不如 ROWNUMOracle 语法$userDB::select(SELECT * FROM USERS WHERE ID ? AND ROWNUM 1,[1])[0]??null;9.5.3 兼容层同时支持 MySQL 和达梦开发环境继续用 MySQL生产用达梦代码里加个判断?php// app/Helper/DbHelper.phpnamespaceApp\Helper;classDbHelper{publicstaticfunctionisDm():bool{returnconfig(database.default)dm8;}// 分页语法兼容publicstaticfunctionpaginate($query,int$page,int$perPage){if(self::isDm()){// 达梦用 OFFSET FETCHSQL Server 语法达梦 8.1.2 支持$offset($page-1)*$perPage;return$query-offset($offset)-limit($perPage)-get();}else{// MySQL 原生return$query-forPage($page,$perPage)-get();}}// 日期函数兼容publicstaticfunctionnow():string{returnself::isDm()?SYSDATE:NOW();}publicstaticfunctiondateAdd(string$column,int$days):string{if(self::isDm()){return$column$days;// 达梦SYSDATE 7}else{returnDATE_ADD($column, INTERVAL$daysDAY);// MySQL}}}使用?php$usersDB::table(DbHelper::isDm()?USERS:users)-whereRaw(DbHelper::isDm()?CREATED_AT ?:created_at ?,[DB::raw(DbHelper::now(). - 7)])-get();9.6 第五步Redis 迁移到 TongRDS9.6.1 TongRDS 安装db-server 上# 1. 解压 TongRDS假设已下载到 /tmp/TongRDS_v1.0.tar.gzcd/optsudotar-zxf/tmp/TongRDS_v1.0.tar.gzsudochown-Rredis:redis /opt/TongRDS# 2. 配置文件兼容 Redis 配置格式sudotee/opt/TongRDS/conf/tongrds.conf/dev/nullEOF bind 0.0.0.0 port 6379 requirepass TongRDS2024 maxmemory 4gb maxmemory-policy allkeys-lru save 900 1 save 300 10 save 60 10000 dbfilename dump.rdb dir /data/tongrds EOF# 3. 启动sudo-uredis /opt/TongRDS/bin/tongrds-server /opt/TongRDS/conf/tongrds.conf# 4. 验证/opt/TongRDS/bin/tongrds-cli-aTongRDS2024# 输入PING 期望输出PONG9.6.2 数据迁移从原 Redis 到 TongRDS# 原 Redis 服务器CentOS上redis-cli--rdb/tmp/redis_dump.rdb# 生成 RDB 快照文件# 拷贝到麒麟服务器scp/tmp/redis_dump.rdb root192.168.1.103:/data/tongrds/dump.rdb# 重启 TongRDS加载 RDB 文件sudopkilltongrds-serversudo-uredis /opt/TongRDS/bin/tongrds-server /opt/TongRDS/conf/tongrds.conf# 验证数据/opt/TongRDS/bin/tongrds-cli-aTongRDS2024# 输入KEYS * 查看是否有原来的 key# 输入GET user:1 验证值是否正确9.6.3 PHP 代码改造Redis → TongRDS好消息TongRDS 兼容 Redis 协议PHP 代码几乎不用改。只需改连接配置?php// config/database.phpredis[clientphpredis,// 或 predisdefault[hostenv(REDIS_HOST,192.168.1.103),passwordenv(REDIS_PASSWORD,TongRDS2024),portenv(REDIS_PORT,6379),database0,],],潜在坑点TongRDS 不支持部分 Redis 新特性如 Streams、Modules检查代码里有没有用到# 搜索项目里是否用了不兼容的命令grep-rXADD\|XREAD\|MODULE LOAD/var/www/myapp/9.7 第六步灰度上线与回滚预案9.7.1 Nginx 分流配置10% 流量到新环境# /etc/nginx/nginx.conf upstream backend_old { server 192.168.1.201:80; # 原 CentOS 环境 } upstream backend_new { server 192.168.1.101:80; # 新麒麟环境 server 192.168.1.102:80; } # 按用户 ID 哈希分流同一用户始终到同一环境避免 session 问题 split_clients ${remote_addr}${http_user_agent} $backend { 10% new; # 10% 走新环境 * old; # 90% 走旧环境 } server { listen 80; server_name www.example.com; location / { if ($backend new) { proxy_pass http://backend_new; } if ($backend old) { proxy_pass http://backend_old; } proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } }9.7.2 监控对比旧环境 vs 新环境# 实时查看两边的 QPS 和错误率# 旧环境tail-f/var/log/nginx/access.log|awk{print $9}|uniq-c# 新环境麒麟tail-f/var/log/nginx/access.log|awk{print $9}|uniq-c# 对比错误率若新环境 5xx 错误率 1%立即回滚9.7.3 回滚预案5 分钟内恢复# 方案 1Nginx 改配置最快30 秒生效sudovi/etc/nginx/nginx.conf# 把 split_clients 的 10% 改成 0%sudonginx-sreload# 方案 2数据库回滚若达梦有数据不一致# 停止新环境写入sudosystemctl stop php-fpm# 从备份恢复 MySQL原环境mysql-uroot-pmyapp/backup/myapp_before_migration.sql# 重新启动旧环境sudosystemctl start httpd# 原 CentOS 的 Web 服务9.8 迁移检查清单打印出来逐项验证## 迁移上线前检查清单 ### 环境层 - [ ] 麒麟 V10 内核参数已优化sysctl -p - [ ] SELinux 已关闭或配置白名单 - [ ] 防火墙已放行端口80/443/5236/6379 - [ ] 文件描述符上限 65535 ### 数据库层 - [ ] 达梦数据库已启动systemctl status dm8 - [ ] 业务表已创建且数据一致行数对比 - [ ] 索引已创建EXPLAIN 查看执行计划 - [ ] 权限已配置myapp 用户能读写所有业务表 - [ ] 备份脚本已配置每天凌晨 2 点全备 ### 应用层 - [ ] PHP 已编译并支持达梦php -m | grep pdo_odbc - [ ] 代码已改造表名大写、SQL 语法兼容 - [ ] Session 存储已切换到 TongRDS - [ ] 日志路径已配置/var/log/php-fpm/ - [ ] Crontab 定时任务已迁移 ### 测试层 - [ ] 功能测试通过核心业务流程走一遍 - [ ] 压力测试通过QPS 达到原环境的 80% 以上 - [ ] 兼容性测试不同浏览器、移动端 - [ ] 国密 HTTPS 测试证书是 SM2 ### 监控层 - [ ] 日志采集已配置rsyslog → 日志中心 - [ ] Prometheus 已抓取指标 - [ ] 告警规则已配置CPU 80%、错误率 1% - [ ] Grafana 看板已就绪 ### 应急层 - [ ] 回滚脚本已准备/opt/scripts/rollback.sh - [ ] 原环境保留 7 天不删除随时可切回 - [ ] 值班人员电话已登记24 小时响应