达梦读写分离集群是DM8提供的一个用于提升并发事务处理性能的集群组件,它通过创新的架构设计实现了事务级别的读写操作自动分离。读写分离集群底层依赖数据守护机制——主库包揽所有的写入和修改操作,备库在实时同步主库数据的同时,帮主库分担查询的压力。
本文完整记录在CentOS 7虚拟机上搭建达梦DM8两节点读写分离集群的全过程,包括部署、同步测试、读写分发比例配置,以及与主备集群的差异对比。
适用场景:最适合“读多写少”的业务模型。例如,管理员发布通知(写入操作只有1次并发),但成千上万的用户查看通知(读取操作可能有上万次并发),所有查询压力被分流到备库,主库在海量并发下依然能稳如泰山
本实验环境为一台虚拟机配置双网卡,主备库运行在同一物理机上,通过不同网卡和端口隔离:
| 角色 | IP地址 | 实例名 | 数据库端口 | MAL端口 | 守护端口 | 实例监听守护端口 |
|---|---|---|---|---|---|---|
| 主库 | 192.168.200.18 | GRP1_RT_01 | 5236 | 6236 | 7236 | 8236 |
| 备库 | 192.168.201.90 | GRP1_RT_02 | 5237 | 6237 | 7237 | 8237 |
| 确认监视器 | 192.168.200.18 | — | — | — | — | — |
端口说明:
数据库端口(5236/5237)供业务连接;
MAL端口(6236/6237)用于集群内部日志传输;
守护端口(7236/7237)供守护进程通信;
实例监听守护端口(8236/8237)供监视器连接。
/home/dmdba/dmdbms/data/dmdata1/DAMENG//data/dmdata2/DAMENG/Admin2026在主库终端执行:
# 确认两个IP都能ping通(本机双网卡)
ping -c 3 192.168.200.18
ping -c 3 192.168.201.90
# 切换到dmdba用户
su - dmdba
# 检查主库进程
ps -ef | grep dmserver | grep 5236
# 检查备库进程
ps -ef | grep dmserver | grep 5237
# 如有进程,先停止(使用DmService脚本或kill)
注意:由于之前有别的技术操作,如果之前已启动过实例,务必先正常关闭,避免端口冲突。
su - dmdba vi /data/dmdata1/DAMENG/dm.ini
找到以下四个参数,修改为指定值(如不存在则手动添加):
ALTER_MODE_STATUS = 0
ENABLE_OFFLINE_TS = 2
MAL_INI = 1
ARCH_INI = 1
保存退出(:wq)。
注意:
ALTER_MODE_STATUS=0表示禁止手动修改数据库模式,由守护进程统一管理。MAL_INI=1和ARCH_INI=1分别开启MAL系统和归档功能。
MAL(Message Access Layer)是集群节点间的通信机制,通过 dmmal.ini 配置实现日志传输和状态同步。主库和备库的 dmmal.ini 内容必须完全一致。
vi /data/dmdata1/DAMENG/dmmal.ini
写入以下内容:
MAL_CHECK_INTERVAL = 5
MAL_CONN_FAIL_INTERVAL = 5
[MAL_INST1]
MAL_INST_NAME = GRP1_RT_01
MAL_HOST = 192.168.200.18
MAL_PORT = 6236
MAL_INST_HOST = 192.168.200.18
MAL_INST_PORT = 5236
MAL_DW_PORT = 7236
MAL_INST_DW_PORT = 8236
[MAL_INST2]
MAL_INST_NAME = GRP1_RT_02
MAL_HOST = 192.168.201.90
MAL_PORT = 6237
MAL_INST_HOST = 192.168.201.90
MAL_INST_PORT = 5237
MAL_DW_PORT = 7237
MAL_INST_DW_PORT = 8237
注意:
MAL_HOST必须绑定具体的网卡IP,不能写0.0.0.0或主机名,防止解析错误。
读写分离集群通常采用即时归档(TIMELY),即日志写入联机日志文件后发送给备库。
vi /data/dmdata1/DAMENG/dmarch.ini
写入:
[ARCHIVE_LOCAL1]
ARCH_TYPE = LOCAL
ARCH_DEST = /data/dmdata1/DAMENG/arch
ARCH_FILE_SIZE = 512
ARCH_SPACE_LIMIT = 51200
[ARCHIVE_TIMELY1]
ARCH_TYPE = TIMELY
ARCH_DEST = GRP1_RT_02
注意:
ARCH_DEST指向备库的实例名GRP1_RT_02,确保与dmmal.ini中的实例名一致。
守护进程(dmwatcher)运行在各节点,负责监控数据库状态,触发故障切换。
vi /data/dmdata1/DAMENG/dmwatcher.ini
写入:
[GRP1]
DW_TYPE = GLOBAL
DW_MODE = MANUAL
DW_ERROR_TIME = 10
INST_RECOVER_TIME = 60
INST_ERROR_TIME = 10
INST_OGUID = 45331
INST_INI = /data/dmdata1/DAMENG/dm.ini
INST_AUTO_RESTART = 1
RLOG_SEND_THRESHOLD = 0
RLOG_APPLY_THRESHOLD = 0
注意:
DW_TYPE=GLOBAL表示全局守护类型,主备库均使用此类型。DW_MODE=MANUAL为手动切换模式,便于学习验证;生产环境可改为AUTO实现自动故障切换。INST_OGUID是集群唯一标识,主备库必须一致。
su - dmdba vi /data/dmdata2/DAMENG/dm.ini
修改同样的四个参数:
ALTER_MODE_STATUS = 0
ENABLE_OFFLINE_TS = 2
MAL_INI = 1
ARCH_INI = 1
直接复制主库的 dmmal.ini:
cp /data/dmdata1/DAMENG/dmmal.ini /data/dmdata2/DAMENG/dmmal.ini
备库只需配置本地归档:
vi /data/dmdata2/DAMENG/dmarch.ini
写入:
[ARCHIVE_LOCAL1]
ARCH_TYPE = LOCAL
ARCH_DEST = /data/dmdata2/DAMENG/arch
ARCH_FILE_SIZE = 512
ARCH_SPACE_LIMIT = 51200
关键:备库的
dmarch.ini必须额外添加TIMELY归档指向主库,否则GLOBAL类型的守护进程启动时会报错。
修改如下:
vi /data/dmdata2/DAMENG/dmarch.ini
追加:
[ARCHIVE_TIMELY1]
ARCH_TYPE = TIMELY
ARCH_DEST = GRP1_RT_01
最终备库 dmarch.ini 完整内容为:
[ARCHIVE_LOCAL1]
ARCH_TYPE = LOCAL
ARCH_DEST = /data/dmdata2/DAMENG/arch
ARCH_FILE_SIZE = 512
ARCH_SPACE_LIMIT = 51200
[ARCHIVE_TIMELY1]
ARCH_TYPE = TIMELY
ARCH_DEST = GRP1_RT_01
vi /data/dmdata2/DAMENG/dmwatcher.ini
写入(注意 INST_INI 指向备库路径):
[GRP1]
DW_TYPE = GLOBAL
DW_MODE = MANUAL
DW_ERROR_TIME = 10
INST_RECOVER_TIME = 60
INST_ERROR_TIME = 10
INST_OGUID = 45331
INST_INI = /data/dmdata2/DAMENG/dm.ini
INST_AUTO_RESTART = 1
RLOG_SEND_THRESHOLD = 0
RLOG_APPLY_THRESHOLD = 0
监视器(dmmonitor)负责监控集群状态和协调故障切换。
mkdir -p /data/dmdata1/monitor vi /data/dmdata1/monitor/dmmonitor.ini
写入:
MON_DW_CONFIRM = 1
MON_LOG_PATH = /data/dmdata1/monitor/log
MON_LOG_INTERVAL = 60
[GRP1]
MON_INST_OGUID = 45331
MON_DW_IP = 192.168.200.18:7236
MON_DW_IP = 192.168.201.90:7237
注意:
MON_DW_CONFIRM=1表示确认监视器,用于自动故障切换场景。
为避免每次输入完整路径,设置环境变量:
echo 'export DM_HOME=/home/dmdba/dmdbms' >> ~/.bash_profile
echo 'export PATH=$DM_HOME/bin:$PATH' >> ~/.bash_profile
source ~/.bash_profile
关键顺序:必须先以Mount方式启动主备库 → 设置OGUID和模式 → 启动守护进程 → 启动监视器。
su - dmdba dmserver /data/dmdata1/DAMENG/dm.ini mount
看到 SYSTEM IS READY 表示启动成功,保持此终端运行。
新开终端:
su - dmdba dmserver /data/dmdata2/DAMENG/dm.ini mount
保持此终端运行。
新开终端,连接主库:
disql SYSDBA/Admin2026@192.168.200.18:5236
执行:
SP_SET_OGUID(45331);
ALTER DATABASE PRIMARY;
验证:
SELECT DB_MAGIC, MODE$ FROM V$DATABASE;
确认 MODE$ 显示为 PRIMARY,输入 exit 退出。
新开终端,连接备库:
disql SYSDBA/Admin2026@192.168.201.90:5237
执行:
SP_SET_OGUID(45331);
ALTER DATABASE STANDBY;
验证:
SELECT DB_MAGIC, MODE$ FROM V$DATABASE;
确认 MODE$ 显示为 STANDBY,输入 exit 退出。
dmwatcher /data/dmdata1/DAMENG/dmwatcher.ini
看到 DMWATCHER[4.0] IS READY 表示成功,保持运行。
dmwatcher /data/dmdata2/DAMENG/dmwatcher.ini
保持运行。
dmmonitor /data/dmdata1/monitor/dmmonitor.ini
在监视器命令行输入:
show
应看到类似输出:
INSTANCE STATUS MODE
GRP1_RT_01 OPEN PRIMARY
GRP1_RT_02 OPEN STANDBY
如果两个实例均为 OPEN 状态,说明集群搭建成功。
disql SYSDBA/Admin2026@192.168.200.18:5236
执行:
CREATE TABLE TEST_RW (ID INT, NAME VARCHAR(50));
INSERT INTO TEST_RW VALUES (1, 'PRIMARY_INSERT');
COMMIT;
SELECT * FROM TEST_RW;
disql SYSDBA/Admin2026@192.168.201.90:5237
执行:
SELECT * FROM TEST_RW;
如果能立即看到 (1, 'PRIMARY_INSERT'),说明数据同步正常,任务一完成
运行结果如下:
达梦的读写分离通过客户端配置文件 dm_svc.conf 实现,应用通过服务名连接集群,客户端接口根据参数自动完成读写分流。
vi /etc/dm_svc.conf
添加以下内容:
# 定义服务名,包含主备节点
DMRWC=(192.168.200.18:5236,192.168.201.90:5237)
# 开启读写分离
DMRWC_RWSEPARATE=(1)
# 分发比例:主库25%,备库75%
DMRWC_RWSEPARATE_PERCENT=(25,75)
参数说明:
RWSEPARATE=1:开启读写分离功能。RWSEPARATE_PERCENT=(25,75):表示 25% 的读请求发往主库,75% 发往备库。该值表示分发到主库的事务占主备库总事务的百分比,取值范围0~100。
通过服务名连接:
disql SYSDBA/Admin2026@DMRWC
执行查询:
SELECT * FROM TEST_RW;
连接输出会显示实际连接的服务器地址。多次执行观察连接IP的变化,验证分发比例是否生效。
运行结果如下:
任务二完成
| 对比维度 | 实时主备集群 | 读写分离集群(本文搭建) |
|---|---|---|
| 核心目标 | 高可用(HA)——保障业务连续性 | 高性能(HP)+ 高可用——提升吞吐量 |
| 备库角色 | 冷备/温备,一般不对外服务 | 热备,承担读查询负载 |
| 归档类型 | 实时归档(REALTIME) |
即时归档(TIMELY) |
| MAL配置 | 不需要 | 必须配置 dmmal.ini |
| 客户端路由 | 手动指定或依赖IP漂移 | 通过 dm_svc.conf 自动分流 |
| 备库状态 | 通常为 MOUNT | 必须为 OPEN 才能提供读服务 |
| 数据一致性 | 强一致(同步/半同步) | 允许毫秒级延迟(最终一致性) |
| 故障切换 | 支持手动/自动切换 | 同样支持,切换后需更新路由 |
归档模式差异:读写分离集群与主备集群最核心的区别在于归档模式的设置。主备集群通常采用 REALTIME(实时归档),日志在写入联机日志文件之前发送给备库;读写分离集群采用 TIMELY(即时归档),日志在写入联机日志文件之后发送给备库。
客户端分流差异:读写分离集群中,应用通过服务名连接集群,客户端接口先连接主库,主库根据归档配置返回可用备库信息,客户端接口建立备库影子连接,只读事务在备库执行,写事务转回主库执行。
一致性处理差异:读写分离集群存在“写后读”不一致的风险。达梦通过 ARCH_WAIT_APPLY 参数控制:设为1(事务一致模式)时主库等待备库确认重演完成后才提交;设为0(高性能模式,默认)时主库不等待备库重演。
现象:执行 SP_SET_OGUID 或 ALTER DATABASE 时报错 [-720]:Dmwatcher is active。
原因:ALTER_MODE_STATUS 是静态参数,修改后必须重启实例才能生效。
解决方法:
dm.ini 中 ALTER_MODE_STATUS 临时改为 1。ALTER_MODE_STATUS=0,重启。现象:Dmwatcher is GLOBAL type, but has not configured REALTIME or TIMELY archive in dmarch.ini
解决方法:在备库 dmarch.ini 中添加 TIMELY 归档指向主库(参考2.2步骤7)。
现象:备库查询报错 System in mount status。
解决方法:启动备库守护进程后,守护进程会自动将备库切换为 OPEN 状态。或在监视器中执行 open standby GRP1.GRP1_RT_02。
本文完整记录了达梦DM8两节点读写分离集群的搭建过程:
dm.ini、dmmal.ini、dmarch.ini、dmwatcher.ini,启动集群并验证数据同步。dm_svc.conf 配置 RWSEPARATE_PERCENT 参数控制读写分流比例。读写分离集群是在数据守护基础上进一步利用备库资源:主库承担写操作,备库承担部分只读操作。它最适合“读多写少”的业务场景,能在保障高可用的同时显著提升系统吞吐量。
文章
阅读量
获赞
