注册
达梦数据库读写分离和异步集群
技术分享/ 文章详情 /

达梦数据库读写分离和异步集群

DM_336625 2026/07/02 65 0 0

一. 实现原理

读写分离的实现,依赖于驱动(如 DM JDBC、DPI 等)与 dm_svc.conf 文件的深度配合,整个过程对应用层代码透明。其核心路由逻辑如下:

拓扑感知与连接分配:
应用发起连接时,接口会根据 dm_svc.conf 中配置的 IP 列表进行**“裂变访问”,探测并获取当前集群的主、备机信息**。随后,严格根据配置的 LOGIN_MODE(登录模式)参数来返回相应的节点:

0(默认值):优先连主库(Primary) → 其次普通库(Normal) → 最后备库(Standby)

1:只连主库(Primary)

2:只连备库(Standby)

3:优先连备库(Standby) → 其次主库(Primary) → 最后普通库(Normal)

4:优先连普通库(Normal) → 其次主库(Primary) → 最后备库(Standby)

试探性路由分发:
在开启读写分离RW_SEPARATE=(1)后,接口在处理 SQL 时采用了试错策略

优先抛给备库:接口会优先把 SQL 语句发送到备库去执行。

成功即返回:如果是普通的 SELECT 查询,备库执行成功,结果就直接返回给用户,完美分担压力。

失败切主库:如果是 INSERT/UPDATE/DELETE 或是DDL 语句,备库(因为是只读状态)执行必然会报错。接口在底层瞬间捕获到这个失败后,会立刻将同一个事务里的所有操作,全部打包重新发送给主库去执行。只要发生了切主,该事务周期内的后续所有 SQL 都会死死锁定在主库上,保证数据绝对的一致性。

二. 环境规划

<br />1 机器 2 机器 3 机器(异步)
业务 IP 192.168.163.131 192.168.163.132 192.168.163.135
心跳 IP 192.168.163.133 192.168.163.134 192.168.163.136
实例名 DMPRD1 DMPRD2 DMPRD3
实例端口 15236 15236 15236
MAL 端口 5336 5337 5338
MAL 守护进程端口 5436 5437 5438
守护进程端口 5536 5537 5538
INST_OGUID 45332 45332 45332
守护组 DMPRD DMPRD DMPRD
安装路径 home/dmdba/dmdbms home/dmdba/dmdbms /home/dmdba/dmdbms
实例路径 /dmdata/data2 /dmdata/data2 /dmdata/data2
归档路径 /dmadata/arch2 /dmadata/arch2 /dmadata/arch2
归档上限(MB) 51200 51200 51200
确认监视器 IP 192.168.163.128

三. 主库配置

#安装略,初始化数据库 dminit path=/dmdata/data2 page_size=32 instance_name=dmprd1 extent_size=32 log_size=2048 PORT_NUM=15236 CHARSET=1 sysdba_pwd=Dameng123 SYSAUDITOR_PWD=Dameng123 #启动服务,开启归档 dmserv /dmdata/data2/DAMENG/dm.ini SQL> ALTER DATABASE MOUNT; SQL> ALTER DATABASE ARCHIVELOG; SQL> ALTER DATABASE ADD ARCHIVELOG 'DEST=/dmdata/arch2, TYPE=LOCAL, FILE_SIZE=1024, SPACE_LIMIT=51200'; SQL> ALTER DATABASE OPEN; SQL> CHECKPOINT(100); #备份数据库 backup database backupset '/dmdata/dmbak/fullprdbak0610'; #修改dm.ini SQL> SP_SET_PARA_VALUE (2,'PORT_NUM',15236); SQL> SP_SET_PARA_VALUE (2,'DW_INACTIVE_INTERVAL',60); -- 守护进程心跳间隔 SQL> SP_SET_PARA_VALUE (2,'ALTER_MODE_STATUS',0); -- 禁止手工切换主备角色,防止误操作 SQL> SP_SET_PARA_VALUE (2,'ENABLE_OFFLINE_TS',2); -- 允许备库表空间脱机 SQL> SP_SET_PARA_VALUE (2,'MAL_INI',1); -- 开启 MAL 通信,集群必须开 SQL> SP_SET_PARA_VALUE (2,'ARCH_INI',1); -- 开启归档,集群必须开 SQL> SP_SET_PARA_VALUE (2,'TIMER_INI',1); -- 开启定时器,给异步归档用 SQL> SP_SET_PARA_VALUE (2,'RLOG_SEND_APPLY_MON',64); -- 监控发送/应用日志的滑动窗口大小 #关闭前台实例 #修改dmarch.ini [dmdba@~]$ vi /dmdata/data2/DAMENG/dmarch.ini ARCH_WAIT_APPLY = 0 #0:高性能 1:事务一致 [ARCHIVE_LOCAL] ARCH_TYPE = LOCAL #本地归档类型 ARCH_DEST = /data/dmdata/arch/ #本地归档存放路径 ARCH_FILE_SIZE = 1024 #单个归档大小,单位 MB ARCH_SPACE_LIMIT = 51200 #归档上限,单位 MB [ARCHIVE_REALTIME1] ARCH_TYPE = REALTIME #实时归档类型 ARCH_DEST = DMPRD2 #实时归档目标实例名 [ARCHIVE_ASYNC] ARCH_TYPE = ASYNC # 异步归档,按定时器批量推 ARCH_DEST = DMPRD3 # 目标是异步备库的实例名 ARCH_TIMER_NAME = TIMER1 # 关联哪个定时器(在 dmtimer.ini 里定义) #修改dmmal.ini [dmdba@~]$ vi /dmdata/data2/DAMENG/dmmal.ini MAL_CHECK_INTERVAL = 10 #MAL 链路检测时间间隔 MAL_CONN_FAIL_INTERVAL = 10 #判定 MAL 链路断开的时间 MAL_TEMP_PATH = /data/dmdata/malpath/ #临时文件目录 MAL_BUF_SIZE = 512 #单个 MAL 缓存大小,单位 MB MAL_SYS_BUF_SIZE = 2048 #MAL 总大小限制,单位 MB MAL_COMPRESS_LEVEL = 0 #MAL 消息压缩等级,0 表示不压缩 [MAL_INST1] MAL_INST_NAME = DMPRD1 #实例名,和 dm.ini 的 INSTANCE_NAME 一致 MAL_HOST = 192.168.163.133 #MAL 系统监听 TCP 连接的 IP 地址 MAL_PORT = 5336 #MAL 系统监听 TCP 连接的端口 MAL_INST_HOST = 192.168.163.131 #实例的对外服务 IP 地址 MAL_INST_PORT = 15236 #实例对外服务端口,和 dm.ini 的 PORT_NUM 一致 MAL_DW_PORT = 5436 #实例对应的守护进程监听 TCP 连接的端口 MAL_INST_DW_PORT = 5536 #实例监听守护进程 TCP 连接的端口 [MAL_INST2] MAL_INST_NAME = DMPRD2 MAL_HOST = 192.168.163.134 MAL_PORT = 5337 MAL_INST_HOST = 192.168.163.132 MAL_INST_PORT = 15236 MAL_DW_PORT = 5437 MAL_INST_DW_PORT = 5537 [MAL_INST3] MAL_INST_NAME = DMPRD3 MAL_HOST = 192.168.163.136 MAL_PORT = 5338 MAL_INST_HOST = 192.168.163.135 MAL_INST_PORT = 15236 MAL_DW_PORT = 5438 MAL_INST_DW_PORT = 5538 #配置dmwatcher,这里配置的手动切换 [dmdba@~]$ vi /dmdata/data2/DAMENG/dmwatcher.ini [DMPRD] DW_TYPE = GLOBAL #全局守护类型 DW_MODE = MANUAL #MANUAL:故障手切 AUTO:故障自切 DW_ERROR_TIME = 20 #远程守护进程故障认定时间 INST_ERROR_TIME = 20 #本地实例故障认定时间 INST_RECOVER_TIME = 60 #主库守护进程启动恢复的间隔时间 INST_OGUID = 45331 #守护系统唯一 OGUID 值 INST_INI = /dmdata/data2/DAMENG/dm.ini #dm.ini 文件路径 INST_AUTO_RESTART = 1 #打开实例的自动启动功能 INST_STARTUP_CMD = /home/dmdba/dmdbms/bin/dmserver #命令行方式启动 RLOG_SEND_THRESHOLD = 0 #指定主库发送日志到备库的时间阈值,默认关闭 RLOG_APPLY_THRESHOLD = 0 #指定备库重演日志的时间阈值,默认关闭 #配置timer.ini [dmdba@~]$ vi /dmdata/data2/DAMENG/dmtimer.ini [TIMER1] TYPE = 2 # 按日执行模式 FREQ_MONTH_WEEK_INTERVAL = 1 # 间隔周/月数 FREQ_SUB_INTERVAL = 1 # 间隔天数 FREQ_MINUTE_INTERVAL = 1 # 间隔分钟数,这里设 1 分钟推一次 START_TIME = 00:00:00 END_TIME = 00:00:00 # 开始和结束都是 00:00:00 代表全天有效 DURING_START_DATE = 2020-01-01 01:01:01 DURING_END_DATE = 9999-12-31 23:59:59 NO_END_DATE_FLAG = 1 DESCRIBE = RT TIMER IS_VALID = 1 #拷贝备份文件到备库和异步库 [dmdba@dm4 dmbak]$ scp -r fullprdbak0610/ dmdba@192.168.163.132:/dmdata/dmbak/ [dmdba@dm4 dmbak]$ scp -r fullprdbak0610/ dmdba@192.168.163.135:/dmdata/dmbak/ #注册服务 [root@~]# /home/dmdba/dmdbms/script/root/dm_service_installer.sh -t dmserver -p dmprd1 -dm_ini /dmdata/data2/DAMENG/dm.ini -m mount [root@~]# /home/dmdba/dmdbms/script/root/dm_service_installer.sh -t dmwatcher -p prd1Watcher -watcher_ini /dmdata/data2/DAMENG/dmwatcher.ini

四. 从库配置

#安装略,初始化实例 dminit path=/dmdata/data2 page_size=32 instance_name=dmprd2 extent_size=32 log_size=2048 PORT_NUM=15236 CHARSET=1 sysdba_pwd=Dameng123 SYSAUDITOR_PWD=Dameng123 #恢复数据 [dmdba@~]$ dmrman CTLSTMT="RESTORE DATABASE '/dmdata/data2/DAMENG/dm.ini' FROM BACKUPSET '/dmdata/dmbak/fullprdbak0610'" [dmdba@~]$ dmrman CTLSTMT="RECOVER DATABASE '/dmdata/data2/DAMENG/dm.ini' FROM BACKUPSET '/dmdata/dmbak/fullprdbak0610'" [dmdba@~]$ dmrman CTLSTMT="RECOVER DATABASE '/dmdata/data2/DAMENG/dm.ini' UPDATE DB_MAGIC" #修复dmarch.ini #DaMeng Database Archive Configuration file #this is comments ARCH_WAIT_APPLY = 0 #0:高性能 1:事务一致 [ARCHIVE_LOCAL] ARCH_TYPE = LOCAL #本地归档类型 ARCH_DEST = /data/dmdata/arch/ #本地归档存放路径 ARCH_FILE_SIZE = 1024 #单个归档大小,单位 MB ARCH_SPACE_LIMIT = 51200 #归档上限,单位 MB [ARCHIVE_REALTIME1] ARCH_TYPE = REALTIME #实时归档类型 ARCH_DEST = DMPRD1 #实时归档目标实例名 [ARCHIVE_ASYNC] ARCH_TYPE = ASYNC # 异步归档,按定时器批量推 ARCH_DEST = DMPRD3 # 目标是异步备库的实例名 ARCH_TIMER_NAME = TIMER1 # 关联哪个定时器(在 dmtimer.ini 里定义) #修改dm.ini参数 DW_INACTIVE_INTERVAL = 60 #接收守护进程消息超时时间 ALTER_MODE_STATUS = 0 #不允许手工方式修改实例模式/状态/OGUID ENABLE_OFFLINE_TS = 2 #不允许备库 OFFLINE 表空间 MAL_INI = 1 #打开 MAL 系统 ARCH_INI = 1 #打开归档配置 RLOG_SEND_APPLY_MON = 64 #统计最近 64 次的日志重演信息 TIMER_INI = 1 #dmmal.ini、dmwatcher.ini、dmtimer.ini保持一致 #注册服务 [root@~]# /home/dmdba/dmdbms/script/root/dm_service_installer.sh -t dmserver -p dmprd2 -dm_ini /dmdata/data2/DAMENG/dm.ini -m mount [root@~]# /home/dmdba/dmdbms/script/root/dm_service_installer.sh -t dmwatcher -p prd2Watcher -watcher_ini /dmdata/data2/DAMENG/dmwatcher.ini

五. 异步备库

#安装略,初始化实例 dminit path=/dmdata/data2 page_size=32 instance_name=dmprd2 extent_size=32 log_size=2048 PORT_NUM=15236 CHARSET=1 sysdba_pwd=Dameng123 SYSAUDITOR_PWD=Dameng123 #恢复数据 [dmdba@~]$ dmrman CTLSTMT="RESTORE DATABASE '/dmdata/data2/DAMENG/dm.ini' FROM BACKUPSET '/dmdata/dmbak/fullprdbak0610'" [dmdba@~]$ dmrman CTLSTMT="RECOVER DATABASE '/dmdata/data2/DAMENG/dm.ini' FROM BACKUPSET '/dmdata/dmbak/fullprdbak0610'" [dmdba@~]$ dmrman CTLSTMT="RECOVER DATABASE '/dmdata/data2/DAMENG/dm.ini' UPDATE DB_MAGIC" #修改系统参数dm.ini DW_INACTIVE_INTERVAL = 60 #接收守护进程消息超时时间 RLOG_SEND_APPLY_MON = 64 #统计最近 64 次的日志重演信息 ALTER_MODE_STATUS = 0 #不允许手工方式修改实例模式/状态/OGUID ENABLE_OFFLINE_TS = 2 #不允许备库 OFFLINE 表空间 MAL_INI = 1 #打开 MAL 系统 ARCH_INI = 1 #打开归档配置 TIMER_INI = 1 #修改dmwatcher.ini [DMPRD] DW_TYPE = LOCAL #本地守护类型 DW_MODE = MAMUAL #MANUAL:故障手切 AUTO:故障自切 DW_ERROR_TIME = 20 #远程守护进程故障认定时间 INST_ERROR_TIME = 20 #本地实例故障认定时间 INST_RECOVER_TIME = 60 #主库守护进程启动恢复的间隔时间 INST_OGUID = 45331 #守护系统唯一 OGUID 值 INST_INI = /dmdata/data2/DAMENG/dm.ini #dm.ini 文件路径 INST_AUTO_RESTART = 1 #打开实例的自动启动功能 INST_STARTUP_CMD = /home/dmdba/dmdbms/bin/dmserver #命令行方式启动 RLOG_SEND_THRESHOLD = 0 #指定主库发送日志到备库的时间阈值,默认关闭 RLOG_APPLY_THRESHOLD = 0 #指定备库重演日志的时间阈值,默认关闭 #修改dmarch.ini,异步只本地备份即可 ARCH_WAIT_APPLY = 0 #0:高性能 1:事务一致 [ARCHIVE_LOCAL] ARCH_TYPE = LOCAL #本地归档类型 ARCH_DEST = /data/dmdata/arch/ #本地归档存放路径 ARCH_FILE_SIZE = 1024 #单个归档大小,单位 MB ARCH_SPACE_LIMIT = 51200 #归档上限,单位 MB #注册服务 [root@~]# /home/dmdba/dmdbms/script/root/dm_service_installer.sh -t dmserver -p dmprd3 -dm_ini /dmdata/data2/DAMENG/dm.ini -m mount [root@~]# /home/dmdba/dmdbms/script/root/dm_service_installer.sh -t dmwatcher -p prd3Watcher -watcher_ini /dmdata/data2/DAMENG/dmwatcher.ini

六. 配置监视器

[dmdba@~]$ vi /home/dmdba/dmdbms/bin/dmmonitordmprd.ini MON_DW_CONFIRM = 0 #0:非确认(故障手切) 1:确认(故障自切) MON_LOG_PATH = /home/dmdba/prdlog #监视器日志文件存放路径 MON_LOG_INTERVAL = 60 #每隔 60s 定时记录系统信息到日志文件 MON_LOG_FILE_SIZE = 512 #单个日志大小,单位 MB MON_LOG_SPACE_LIMIT = 2048 #日志上限,单位 MB [DMPRD] MON_INST_OGUID = 45331 #组 GRP1 的唯一 OGUID 值 MON_DW_IP = 192.168.163.133:5436 #IP 对应 MAL_HOST,PORT 对应 MAL_DW_PORT MON_DW_IP = 192.168.163.134:5437 MON_DW_IP = 192.168.163.136:5438 #注册服务 [root@~]# /home/dmdba/dmdbms/script/root/dm_service_installer.sh -t dmmonitor -p Monitor -monitor_ini /home/dmdba/dmdbms/bin/dmmonitordmprd.ini

七. 启动服务

#启动数据库修改参数 ##A 主 [dmdba@dm4 ~]$ dmserver /dmdata/data2/DAMENG/dm.ini mount [dmdba@dm4 ~]$ disql sysdba/Dameng123@localhost:15236 SQL> SP_SET_OGUID(45331); SQL> ALTER DATABASE PRIMARY; ##B 备 [dmdba@dm4 ~]$ dmserver /dmdata/data2/DAMENG/dm.ini mount [dmdba@dm4 ~]$ disql sysdba/Dameng123@localhost:15236 SQL> SP_SET_OGUID(45331); SQL> ALTER DATABASE STANDBY; ##C 异步 [dmdba@dm4 ~]$ dmserver /dmdata/data2/DAMENG/dm.ini mount [dmdba@dm4 ~]$ disql sysdba/Dameng123@localhost:15236 SQL> SP_SET_OGUID(45331); SQL> ALTER DATABASE STANDBY; #启动守护进程,主备异步的顺序 dmwatcher /dmdata/data2/DAMENG/dmwatcher.ini #启动监视器查看集群状态 dmmonitor dmdbms/bin/dmmonitorprd.ini

读写分离配置

vim /etc/dm_svc.conf ##以#开头的行表示是注释 ##全局配置区 TIME_ZONE=(480) LANGUAGE=(cn) DMRW=(192.168.163.131:15236,192.168.163.132:15236,192.168.163.135:15236) ##服务配置 [DMRW] LOGIN_MODE=(1) RW_SEPARATE=(1) RW_PERCENT=(30) SWITCH_TIMES=(60) SWITCH_INTERVAL=(1000) LOGIN_MODE 指定优先登录的服务器模式。0:优先连接 PRIMARY 模式的库,NORMAL 模式次之,最后选择 STANTBY 模式; 1:只连接主库;2:只连接备库;3:优先连接 STANDBY 模式的库,PRIMARY 模式次之,最后选择 NORMAL 模式; 4:优先连接 NORMAL 模式的库,PRIMARY 模式次之,最后选择 STANDBY 模式。 SWITCH_TIMES 表示以服务名连接数据库时,若未找到符合条件的库成功建立连接,将尝试遍历服务名中库列表的次数。有效值范围 1~9223372036854775807,默认值为 1,可以设置至少 3 次用来避免由于网卡的波动,造成数据库连接测频繁切换。 SWITCH_INTERVAL 表示在服务器之间切换的时间间隔,单位为毫秒,有效值范围 1~9223372036854775807。与参数 SWITCH_TIMES、EP_SELECTOR 配合使用,EP_SELECTOR 设置为 0,等待 SWITCH_INTERVAL 后会切换尝试连接下一个服务器,EP_SELECTOR 设置为 1,等待 SWITCH_INTERVAL 后会继续尝试连接该服务器,直到 SWITCH_TIMES 次再切换下一个服务器。 RW_SEPARATE 表示是否启用读写分离。0:不启用;1:启用;2:启用,备库由客户端进行选择,且只会选择服务名中配置的节点。 RW_PERCENT 表示读写分离分发比例,有效值范围 0~100,主库占所有事物数的比例。可以根据主备库的实际压力来设定。

达梦社区技术 https://eco.dameng.com

评论
后发表回复

作者

文章

阅读量

获赞

扫一扫
联系客服