达梦数据库实例迁移教学文档
适用场景:服务器根目录
/磁盘空间不足,需要将达梦数据库实例从系统盘迁移到数据盘
数据库版本:达梦 DM8
操作系统:Linux(ARM/aarch64 或 x86 均可)
预估耗时:1–2 小时(取决于数据量)
风险等级:⚠️ 高(生产环境,需停机)
文档中所有
<占位符>需替换为实际环境值后再执行。
目录
一、迁移前必读:判断你的环境
1.1 什么是"根目录满了"?
Linux 系统的 /(根目录)相当于 Windows 的 C 盘。如果根目录 100% 满,系统会:
- 无法创建新文件(连日志都写不了)
- 数据库可能突然崩溃
- 无法登录或执行命令
你的根目录是不是满了?查一下:
df -h /
| 结果 | 含义 | 处理方式 |
|---|---|---|
Use% >= 95% |
🚨 危险,随时可能崩溃 | 建议立即迁移 |
Use% 85%–94% |
⚠️ 告警,需要尽快处理 | 尽快安排迁移 |
Use% < 85% |
✅ 安全 | 暂时无需迁移 |
1.2 数据库装在哪里?
达梦数据库默认安装在 /dm8,数据文件在 /dm8/data/<实例名>/ 下。
你需要确认:数据库数据文件是否在根目录下?
# 查看数据库进程,找到 dm.ini 路径
ps -ef | grep dmserver
如果显示 path=/dm8/data/<实例名>/dm.ini,说明数据库在根目录,需要迁移。
1.3 目标盘(数据盘)空间够不够?
df -h
找到你的数据盘(通常是 /data 或 /opt 或外挂磁盘),确认:
- 可用空间 > 数据库数据量 × 2(比如数据库 50G,目标盘至少 100G 可用,参考 1.2 节公式)
💡 为什么 ×2? 因为迁移过程中可能同时存在旧数据 + 新数据 + 备份集。
二、前置检查清单
以下检查在迁移前完成,逐项打勾后再继续。
✅ 检查 1:确认数据库是单机还是主备集群
ps -ef | grep -E "dmserver|dmwatcher|dmmonitor"
| 看到什么 | 说明 | 本教程适用性 |
|---|---|---|
只有 dmserver |
单机 | ✅ 完全适用 |
dmserver + dmwatcher |
主备集群 | ⚠️ 本教程仅适用于单机部分,主备需额外配置 |
dmserver + dmmonitor |
主备集群 | ⚠️ 同上 |
本教程默认你是单机环境。 如果是主备集群,建议先咨询达梦技术支持。
✅ 检查 2:确认数据库参数
这些参数决定了新实例的创建方式,和原库保持一致。
su - dmdba
cd /dm8/bin
./disql SYSDBA/'"<SYSDBA密码>"'
-- 在 SQL> 提示符下执行:
checkpoint(100);
select DECODE(para_value,1,'是','否') as "LENGTH_IN_CHAR",
page as "PAGE_SIZE",
SF_GET_EXTENT_SIZE() as "EXTENT_SIZE",
DECODE(unicode,'1','utf8',0,'gbk','EUC-KR') as "CHARSET",
decode(CASE_SENSITIVE,'1','敏感','不敏感') as CASE_SENSITIVE
from v$dm_ini
where para_name = 'LENGTH_IN_CHAR';
把结果记下来,后面 dminit 要用。
✅ 检查 3:确认密码格式
达梦密码如果包含特殊字符(如 @、!、#),登录时需要特殊引号:
# 假设密码是 <密码样例>
./disql SYSDBA/'"<密码样例>"'
# 外层单引号,内层双引号,密码包在双引号里
如果密码是纯字母数字,可以直接:
./disql SYSDBA/<密码>
✅ 检查 4:通知业务方停写数据
迁移过程需要停库,期间数据库无法提供服务。提前通知:
- 应用开发团队
- 业务使用方
- 数据同步/ETL 任务负责人
三、方案选择:走哪条路?
根据你的磁盘空间情况,选择方案:
开始
│
▼
目标盘可用空间 > 数据量 × 2 ?
│
┌─────────┴─────────┐
│ │
是 否
│ │
▼ ▼
走【方案 A】 走【方案 B】
备份还原法 直接拷贝法
(dmrman) (cp)
更规范,有备份集 更省空间,无备份集
| 对比项 | 方案 A:备份还原 | 方案 B:直接拷贝 |
|---|---|---|
| 适用条件 | 目标盘空间 > 数据量 × 2 | 目标盘空间 > 数据量 × 1.2 |
| 优点 | 有完整备份集,可回退 | 不占用额外空间,速度较快 |
| 缺点 | 备份集占用较多空间 | 无独立备份集,回退依赖旧实例 |
| 停机时间 | 较长(备份 + 还原) | 较短(仅拷贝时间) |
| 推荐度 | ⭐⭐⭐ | ⭐⭐⭐⭐⭐(空间紧张时) |
本案例实际采用方案 B,因为数据盘空间紧张,备份集较大导致还原失败。
四、方案 A:备份还原法(dmrman)
⚠️ 注意:如果目标盘空间不足,此方案会失败。建议先评估空间,或直接跳到【方案 B】。
步骤 1:创建备份目录
# root 执行
mkdir -p /data/dmbak
mkdir -p /data/dmdb
chown -R dmdba:dinstall /data/dmbak /data/dmdb
chmod 755 /data/dmbak /data/dmdb
步骤 2:停库
su - dmdba
cd /dm8/bin
# 停库(服务名格式为 DmService<实例名>,下面以常见命名示例,请替换为你的实际值)
./DmService<实例服务名> stop
# 确认已停(应该看不到 dmserver 进程)
ps -ef | grep dmserver
服务名确认方式:
ls /dm8/bin/DmService*,参见 Q2。
步骤 3:冷备(dmrman)
./dmrman use_ap=2
# 在 RMAN> 提示符下执行:
backup database '/dm8/data/<实例名>/dm.ini'
backupset '/data/dmbak/bakfull_YYYYMMDD'
compressed level 1 parallel 4;
参数说明:
compressed level 1:压缩级别 1(1–9,数字越大压缩率越高,耗时越长)parallel 4:4 线程并行(根据 CPU 核数调整)
等待备份完成,看到 backup successfully! 后 exit 退出。
步骤 4:创建新实例
用【检查 2】查到的参数替换下面的值:
cd /dm8/bin
./dminit path=/data db_name=<实例名> instance_name=<实例名> \
EXTENT_SIZE=<值> PAGE_SIZE=<值> CASE_SENSITIVE=<Y/N> CHARSET=<值> LENGTH_IN_CHAR=<值>
参数和原库保持一致,特别是
PAGE_SIZE和CASE_SENSITIVE,不一致会导致还原失败。
步骤 5:拷贝并修改 dm.ini
# 拷贝原配置文件
cp -f /dm8/data/<实例名>/dm.ini /data/<实例名>/dm.ini
# 批量替换所有路径
sed -i 's|/dm8/data/<实例名>|/data/<实例名>|g' /data/<实例名>/dm.ini
# 验证(应该无输出)
grep -n "/dm8/data/<实例名>" /data/<实例名>/dm.ini
步骤 6:还原数据库
./dmrman use_ap=2
# 依次执行三条命令:
restore database '/data/<实例名>/dm.ini' from backupset '/data/dmbak/bakfull_YYYYMMDD';
recover database '/data/<实例名>/dm.ini' from backupset '/data/dmbak/bakfull_YYYYMMDD';
recover database '/data/<实例名>/dm.ini' update db_magic;
如果报错 [-523]:磁盘空间不足 → 说明目标盘不够,建议改用方案 B 或先扩容。
步骤 7:修改服务脚本并启动
# root 执行
sed -i 's|/dm8/data/<实例名>/dm.ini|/data/<实例名>/dm.ini|g' /dm8/bin/DmService<实例服务名>
# dmdba 执行启动
su - dmdba
cd /dm8/bin
./DmService<实例服务名> start
五、方案 B:直接拷贝法(cp)⭐ 推荐
适用场景:目标盘空间紧张,无法容纳备份集 + 原数据两份拷贝。
原理:直接复制原库数据文件到新位置,不经过备份集,节省空间。
步骤 1:确认目标盘空间
df -h /data
# 确认可用空间 > 原库数据量 × 1.2
du -sh /dm8/data/<实例名>
# 记录原库大小
步骤 2:停库
su - dmdba
cd /dm8/bin
./DmService<实例服务名> stop
# 确认已停
ps -ef | grep dmserver
步骤 3:直接拷贝数据文件(关键步骤)
# 必须用 dmdba 用户执行,保留文件权限!
su - dmdba
cp -rp /dm8/data/<实例名> /data/<实例名>
⚠️ 重要提醒:
- 不要用 root 执行
cp,否则文件所有者变成 root,数据库无法启动。- 拷贝时间取决于数据量(如示例规模约 5–10 分钟量级),不要按 Ctrl+C 中断。
- 如果中断了,需要删除不完整拷贝后重新来:
rm -rf /data/<实例名> cp -rp /dm8/data/<实例名> /data/<实例名>
步骤 4:验证拷贝完整性
# 检查大小是否和原库一致
du -sh /data/<实例名>
# 应该和原库大小一致
# 检查文件所有者
ls -la /data/<实例名> | head -5
# 应该显示 dmdba:dinstall
步骤 5:修改 dm.ini 路径
# 批量替换所有旧路径为新路径
sed -i 's|/dm8/data/<实例名>|/data/<实例名>|g' /data/<实例名>/dm.ini
# 验证替换干净(应该无输出)
grep -n "/dm8/data/<实例名>" /data/<实例名>/dm.ini
步骤 6:修改服务启动脚本
# root 执行
sed -i 's|/dm8/data/<实例名>/dm.ini|/data/<实例名>/dm.ini|g' /dm8/bin/DmService<实例服务名>
# 验证修改
grep "INI_PATH" /dm8/bin/DmService<实例服务名>
# 应显示:INI_PATH="/data/<实例名>/dm.ini"
步骤 7:启动并验证
su - dmdba
cd /dm8/bin
./DmService<实例服务名> start
# 登录验证
./disql SYSDBA/'"<SYSDBA密码>"'
# 检查状态
select status$ from v$instance;
-- 预期:OPEN
六、迁移后验证
6.1 验证数据库状态
./disql SYSDBA/'"<SYSDBA密码>"'
-- 检查实例状态
select status$ from v$instance;
-- 预期:OPEN
-- 检查数据库角色
select name, role$, mode$ from v$instance;
-- 预期:name=<实例名>, role$=NORMAL, mode$=NORMAL
6.2 验证数据完整性
-- 查看有哪些业务用户(排除系统用户)
select owner, table_name from dba_tables
where owner not in ('SYS', 'SYSDBA', 'SYSAUDITOR')
and rownum < 50;
-- 抽查几个关键表的数据量
select count(*) from <业务用户>.<业务表>;
6.3 验证应用连接
让业务方测试:
- 应用能否正常连接数据库?
- 数据查询是否正常?
- 写入操作是否正常?
全部通过后再继续下一步。
七、清理旧实例
7.1 第一步:保留旧实例(保险做法)
# 不要直接删除!先重命名保留
mv /dm8/data/<实例名> /dm8/data/<实例名>.bak.YYYYMMDD
建议保留 1–2 天,确认新实例完全稳定后再删除。
7.2 第二步:真正释放空间(关键!)
# 注意:mv 在同一磁盘内只是重命名,不释放空间!
# 必须 rm 删除才能真正释放根目录空间
rm -rf /dm8/data/<实例名>.bak.YYYYMMDD
# 验证空间释放
df -h /
7.3 清理后的空间检查
du -sh /* 2>/dev/null | sort -rh | head -10
如果根目录使用率仍然偏高,检查是否有其他大文件可以清理(如旧日志、安装包等)。
八、常见问题与故障排查
Q1:disql 登录报错"用户名或密码错误"
原因:密码包含特殊字符,引号格式不对。
解决:
# 错误写法
./disql SYSDBA/"<含特殊字符的密码>"
# 正确写法(外层单引号,内层双引号)
./disql SYSDBA/'"<含特殊字符的密码>"'
Q2:服务名找不到(No such file or directory)
原因:服务名写错了。达梦服务名格式是 DmService<实例名>。
解决:
# 查看 bin 目录下有哪些服务脚本
ls /dm8/bin/DmService*
# 用 ls 列出的实际服务名替换下面命令
./DmService<实际服务名> stop
./DmService<实际服务名> start
Q3:还原报错"磁盘空间不足"
原因:目标盘空间不够容纳备份集 + 解压后的数据。
解决:
- 如果目标盘空间 > 数据量 × 1.2,改用【方案 B:直接拷贝法】
- 如果目标盘空间 < 数据量 × 1.2,联系管理员扩容磁盘
Q4:启动后数据库状态是 MOUNT,不是 OPEN
原因:
dm.ini路径修改不完整,某些文件指向旧位置- 数据文件权限不对(所有者不是 dmdba)
解决:
# 检查 dm.ini 中是否还有旧路径
grep "/dm8/data/<实例名>" /data/<实例名>/dm.ini
# 如果有输出,说明路径没替换干净
# 检查文件权限
ls -la /data/<实例名>
# 应该都是 dmdba:dinstall,如果显示 root,说明拷贝时用户不对
Q5:查询表名报错"无效的表或视图名"
原因:数据库开启了大小写敏感(CASE_SENSITIVE=Y),表名包含小写字母。
解决:
-- 错误
select * from <业务用户>.t_sys_role;
-- 正确(加双引号)
select * from <业务用户>."t_sys_role";
Q6:根目录使用率仍然偏高,mv 后没释放空间
原因:mv 在同一磁盘分区(如都在 / 下)只是重命名,不释放空间。
解决:需要使用 rm -rf 删除才能真正释放空间。
九、命令速查表
| 目的 | 命令 |
|---|---|
| 查看磁盘空间 | df -h |
| 查看目录大小 | du -sh /path |
| 查看文件/目录详情 | ls -la /path |
| 查看达梦版本 | cat /dm8/bin/version.txt |
| 登录 disql | ./disql SYSDBA/'"<密码>"' |
| 查询实例参数 | select * from v$dm_ini; |
| 查询版本号 | select id_code(); |
| 停库 | ./DmService<实例服务名> stop |
| 启动库 | ./DmService<实例服务名> start |
| 查看进程 | ps -ef | grep dmserver |
| 冷备(dmrman) | backup database '/path/dm.ini' backupset '/path' compressed level 1 parallel 4; |
| 还原(dmrman) | restore database '/path/dm.ini' from backupset '/path'; |
| 创建实例 | ./dminit path=/data db_name=<实例名> ... |
| 批量替换路径 | sed -i 's|旧路径|新路径|g' 文件 |
| 递归拷贝保留权限 | cp -rp 源目录 目标目录 |
| 查找大文件 | du -sh /path/* 2>/dev/null | sort -rh | head -10 |
| 删除旧日志 | find /dm8/log -name "*.log" -mtime +90 -exec rm -f {} \; |
十、回退方案
如果迁移后发现问题(数据库无法启动、数据丢失等),按以下步骤回退:
10.1 情况一:新实例还没启动,或启动失败
# 1. 删除新实例
rm -rf /data/<实例名>
# 2. 恢复服务脚本指向旧路径
sed -i 's|/data/<实例名>/dm.ini|/dm8/data/<实例名>/dm.ini|g' /dm8/bin/DmService<实例服务名>
# 3. 启动旧实例
su - dmdba
cd /dm8/bin
./DmService<实例服务名> start
10.2 情况二:新实例已启动,但数据有问题
# 1. 停掉新实例
./DmService<实例服务名> stop
# 2. 如果旧实例还在(没删),直接恢复
# 如果旧实例已删,但有备份集,用 dmrman 还原到旧路径
# 3. 恢复服务脚本
sed -i 's|/data/<实例名>/dm.ini|/dm8/data/<实例名>/dm.ini|g' /dm8/bin/DmService<实例服务名>
# 4. 启动旧实例
./DmService<实例服务名> start
10.3 情况三:旧实例已删,且无备份集
⚠️ 这是较坏的情况。如果采用方案 B(直接拷贝)且旧实例已删除,没有备份集,数据无法回退。
预防措施:
- 迁移前保留旧实例至少 1–2 天
- 或先用方案 A 做一份备份集,即使方案 B 失败也有退路
文档状态:✅ 教学文档,可按步骤执行(替换占位符后)
最后更新:2026-07-10

浙公网安备 33010602011771号