| 项目 | DM2(节点0 / db0) | DM3(节点1 / db1) |
|---|---|---|
| 操作系统 | Kylin-Server-V10-SP3 | Kylin-Server-V10-SP3 |
| 心跳IP = 业务IP | 192.168.126.144 | 192.168.126.145 |
| 实例名 | DSC0 | DSC1 |
| DB端口 | 5238 | 5239 |
| CSS端口 | 11286 | 11286 |
| ASM端口 | 11276 | 11276 |
| MAL端口 | 11246 / 11266 | 11246 / 11266 |
| 数据库名 | DSC | DSC |
| OGUID | 210715 | 210715 |
| 大小写 | 不敏感(CASE_SENSITIVE=0) | 不敏感(CASE_SENSITIVE=0) |
| 共享磁盘 | 设备别名 | 大小 | 用途 |
|---|---|---|---|
| 磁盘1 | /dev/dm/asm-dmvote | 2 GB | VOTE 表决磁盘 |
| 磁盘2 | /dev/dm/asm-dmdcr | 2 GB | DCR 集群注册表 |
| 磁盘3 | /dev/dm/asm-dmlog | 10 GB | Redo 日志 |
| 磁盘4 | /dev/dm/asm-dmdata | 50 GB | 数据文件 |
| 磁盘5 | /dev/dm/asm-dmarch | 20 GB | 归档日志 |
以下操作在 **VMware **上执行。
两台虚拟机 DM2 和 DM3 都需要关机后再操作。
在 DM2 虚拟机目录下执行(使用 管理员 PowerShell):
# 进入 DM2 虚拟机所在目录(根据实际路径调整)
cd "你的VMware虚拟机目录"
# 创建 5 块共享磁盘(预先分配、厚置备)
vmware-vdiskmanager.exe -c -s 2GB -a lsilogic -t 2 "shared_vote.vmdk"
vmware-vdiskmanager.exe -c -s 2GB -a lsilogic -t 2 "shared_dcr.vmdk"
vmware-vdiskmanager.exe -c -s 10GB -a lsilogic -t 2 "shared_log.vmdk"
vmware-vdiskmanager.exe -c -s 50GB -a lsilogic -t 2 "shared_data.vmdk"
vmware-vdiskmanager.exe -c -s 20GB -a lsilogic -t 2 "shared_arch.vmdk"
在 DM2 的 .vmx 文件末尾添加共享总线配置和 5 块磁盘:
# ========== 共享存储总线 ==========
scsi1.present = "TRUE"
scsi1.virtualDev = "lsilogic"
scsi1.sharedBus = "virtual"
# ========== 共享磁盘 1 - VOTE (2GB) ==========
scsi1:0.present = "TRUE"
scsi1:0.fileName = "shared_vote.vmdk"
scsi1:0.mode = "independent-persistent"
scsi1:0.deviceType = "disk"
scsi1:0.redo = ""
# ========== 共享磁盘 2 - DCR (2GB) ==========
scsi1:1.present = "TRUE"
scsi1:1.fileName = "shared_dcr.vmdk"
scsi1:1.mode = "independent-persistent"
scsi1:1.deviceType = "disk"
scsi1:1.redo = ""
# ========== 共享磁盘 3 - REDO LOG (10GB) ==========
scsi1:2.present = "TRUE"
scsi1:2.fileName = "shared_log.vmdk"
scsi1:2.mode = "independent-persistent"
scsi1:2.deviceType = "disk"
scsi1:2.redo = ""
# ========== 共享磁盘 4 - DATA (50GB) ==========
scsi1:3.present = "TRUE"
scsi1:3.fileName = "shared_data.vmdk"
scsi1:3.mode = "independent-persistent"
scsi1:3.deviceType = "disk"
scsi1:3.redo = ""
# ========== 共享磁盘 5 - ARCH (20GB) ==========
scsi1:4.present = "TRUE"
scsi1:4.fileName = "shared_arch.vmdk"
scsi1:4.mode = "independent-persistent"
scsi1:4.deviceType = "disk"
scsi1:4.redo = ""
# ========== 磁盘 UUID 支持 ==========
disk.EnableUUID = "TRUE"
在 DM3 的 .vmx 文件末尾添加相同配置,但 fileName 需要指向 DM2 目录下的磁盘(使用绝对路径或相对路径均可,确保指向同一组 .vmdk 文件):
# ========== 共享存储总线 ==========
scsi1.present = "TRUE"
scsi1.virtualDev = "lsilogic"
scsi1.sharedBus = "virtual"
# ========== 共享磁盘(路径指向 DM2 虚拟机目录下的磁盘文件)==========
scsi1:0.present = "TRUE"
scsi1:0.fileName = "F:VM-DM2/shared_vote.vmdk"
scsi1:0.mode = "independent-persistent"
scsi1:0.deviceType = "disk"
scsi1:0.redo = ""
scsi1:1.present = "TRUE"
scsi1:1.fileName = "F:VM-DM2/shared_dcr.vmdk"
scsi1:1.mode = "independent-persistent"
scsi1:1.deviceType = "disk"
scsi1:1.redo = ""
scsi1:2.present = "TRUE"
scsi1:2.fileName = "F:VM-DM2/shared_log.vmdk"
scsi1:2.mode = "independent-persistent"
scsi1:2.deviceType = "disk"
scsi1:2.redo = ""
scsi1:3.present = "TRUE"
scsi1:3.fileName = "F:VM-DM2/shared_data.vmdk"
scsi1:3.mode = "independent-persistent"
scsi1:3.deviceType = "disk"
scsi1:3.redo = ""
scsi1:4.present = "TRUE"
scsi1:4.fileName = "F:VM-DM2/shared_arch.vmdk"
scsi1:4.mode = "independent-persistent"
scsi1:4.deviceType = "disk"
scsi1:4.redo = ""
# ========== 磁盘 UUID 支持 ==========
disk.EnableUUID = "TRUE"
启动 DM2 和 DM3,在两台机器上分别执行:
# 查看共享磁盘是否被识别
fdisk -l | grep -E "Disk /dev/sd"


以下操作在 DM2 和 DM3 两台机器上都执行,使用 root 用户。
# 关闭防火墙
systemctl stop firewalld
systemctl disable firewalld
# 关闭 SELinux
setenforce 0
sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config
cat >> /etc/hosts << 'EOF'
192.168.126.144 dm2
192.168.126.145 dm3
EOF
# 创建用户和组(如已存在则跳过)
groupadd -g 1001 dinstall
useradd -u 1001 -g dinstall -m -d /home/dmdba -s /bin/bash dmdba
echo "dmdba:Dameng@123" | chpasswd
# 创建所需目录
mkdir -p /home/dmdba/dmdbms/dsc_config/DSC0
mkdir -p /home/dmdba/dmdbms/dsc_config/DSC1
mkdir -p /home/dmdba/dmbak
mkdir -p /home/dmdba/dmsqllog
mkdir -p /home/dmdba/core
mkdir -p /home/dmdba/nmon_output
# 授权
chown -R dmdba:dinstall /home/dmdba
chmod -R 755 /home/dmdba/dmdbms
在 DM2 上执行:
su - dmdba
ssh-keygen -t rsa -P "" -f ~/.ssh/id_rsa
ssh-copy-id dmdba@192.168.126.145
在 DM3 上执行:
su - dmdba
ssh-keygen -t rsa -P "" -f ~/.ssh/id_rsa
ssh-copy-id dmdba@192.168.126.144
**验证:**两台机器上互相 ssh dmdba@对方IP 应该不需要密码直接登录。
# /etc/security/limits.conf
cat >> /etc/security/limits.conf << 'EOF'
dmdba soft nofile 65536
dmdba hard nofile 65536
dmdba soft nproc 65536
dmdba hard nproc 65536
dmdba soft core unlimited
dmdba hard core unlimited
EOF
# 使 limits 生效
echo "session required pam_limits.so" >> /etc/pam.d/login
cat >> /etc/sysctl.conf << 'EOF'
# DM 数据库推荐参数
fs.file-max = 6815744
fs.aio-max-nr = 1048576
kernel.sem = 250 32000 100 128
kernel.shmmni = 4096
kernel.shmall = 4294967296
kernel.shmmax = 68719476736
net.ipv4.ip_local_port_range = 9000 65500
net.core.rmem_default = 262144
net.core.rmem_max = 4194304
net.core.wmem_default = 262144
net.core.wmem_max = 1048576
vm.swappiness = 10
vm.dirty_ratio = 80
vm.dirty_background_ratio = 5
EOF
sysctl -p
su - dmdba
cat >> ~/.bash_profile << 'EOF'
export DM_HOME=/home/dmdba/dmdbms
export PATH=$DM_HOME/bin:$DM_HOME/tool:$PATH
export LD_LIBRARY_PATH=$DM_HOME/bin:$LD_LIBRARY_PATH
EOF
source ~/.bash_profile
先在 DM2 上确定 5 块共享磁盘的设备名,然后两台机器执行相同操作。
在 DM2 和 DM3 上分别执行,记录自己的设备名:
fdisk -l | grep "Disk /dev/sd"
lsblk -o NAME,SIZE,TYPE,MOUNTPOINT | grep disk


两台机器上共享磁盘设备名一致(通过大小判断对应关系):
| 大小 | 对应磁盘 | DM2 设备 | DM3 设备 |
|---|---|---|---|
| 2 GB | VOTE | /dev/sdb | /dev/sdb |
| 2 GB | DCR | /dev/sdc | /dev/sdc |
| 10 GB | LOG | /dev/sdd | /dev/sdd |
| 50 GB | DATA | /dev/sde | /dev/sde |
| 20 GB | ARCH | /dev/sdf | /dev/sdf |
如果设备名不一致,以实际为准,后续脚本中用实际的设备名替换。
以 root 用户创建绑定脚本,使用 UUID 方式绑定:
cat > /tmp/uuid_bind.sh << 'SCRIPT'
#!/bin/bash
curr=$(cd "$(dirname "$0")";pwd)
rm -f $curr/88-dm-asmdevices.rules
# 设备映射(根据实际调整)
declare -A disk_map
disk_map["a"]="dmvote" # 第1块磁盘 -> asm-dmvote
disk_map["b"]="dmdcr" # 第2块磁盘 -> asm-dmdcr
disk_map["c"]="dmlog" # 第3块磁盘 -> asm-dmlog
disk_map["d"]="dmdata" # 第4块磁盘 -> asm-dmdata
disk_map["e"]="dmarch" # 第5块磁盘 -> asm-dmarch
for dev in a b c d e; do
uuid=$(/usr/lib/udev/scsi_id --whitelisted --replace-whitespace --device=/dev/sd${dev} 2>/dev/null)
if [ -n "$uuid" ]; then
alias_name=${disk_map[$dev]}
echo "KERNEL==\"sd?\", SUBSYSTEM==\"block\", PROGRAM==\"/usr/lib/udev/scsi_id --whitelisted --replace-whitespace --device=/dev/\$name\", RESULT==\"${uuid}\", SYMLINK+=\"dm/asm-${alias_name}\", OWNER=\"dmdba\", GROUP=\"dinstall\", MODE=\"0660\"" >> $curr/88-dm-asmdevices.rules
fi
done
echo "Generated 88-dm-asmdevices.rules:"
cat $curr/88-dm-asmdevices.rules
SCRIPT
chmod +x /tmp/uuid_bind.sh
bash /tmp/uuid_bind.sh
# DM2 上
cp /tmp/88-dm-asmdevices.rules /etc/udev/rules.d/
scp /tmp/88-dm-asmdevices.rules root@192.168.126.145:/tmp/
# DM3 上
cp /tmp/88-dm-asmdevices.rules /etc/udev/rules.d/
# 触发 udev 规则
udevadm trigger --type=devices --action=change
udevadm control --reload-rules
# 授权
chown dmdba:dinstall /dev/dm/asm-* -R 2>/dev/null
# 验证绑定
ls -la /dev/dm/asm-*


以下所有配置文件先 在 DM2 上创建,再将需分发的文件拷贝到 DM3。
路径:/home/dmdba/dmdbms/dsc_config/dmdcr_cfg.ini
DCR_N_GRP = 3
DCR_VTD_PATH = /dev/dm/asm-dmvote
DCR_OGUID = 210715
[GRP]
DCR_GRP_TYPE = CSS
DCR_GRP_NAME = GRP_CSS
DCR_GRP_N_EP = 2
DCR_GRP_DSKCHK_CNT = 65
[GRP_CSS]
DCR_EP_NAME = CSS0
DCR_EP_HOST = 192.168.126.144
DCR_EP_PORT = 11286
[GRP_CSS]
DCR_EP_NAME = CSS1
DCR_EP_HOST = 192.168.126.145
DCR_EP_PORT = 11286
[GRP]
DCR_GRP_TYPE = ASM
DCR_GRP_NAME = GRP_ASM
DCR_GRP_N_EP = 2
DCR_GRP_DSKCHK_CNT = 61
[GRP_ASM]
DCR_EP_NAME = ASM0
DCR_EP_SHM_KEY = 42424
DCR_EP_SHM_SIZE = 1024
DCR_EP_HOST = 192.168.126.144
DCR_EP_PORT = 11276
DCR_EP_ASM_LOAD_PATH = /dev/dm
[GRP_ASM]
DCR_EP_NAME = ASM1
DCR_EP_SHM_KEY = 42425
DCR_EP_SHM_SIZE = 1024
DCR_EP_HOST = 192.168.126.145
DCR_EP_PORT = 11276
DCR_EP_ASM_LOAD_PATH = /dev/dm
[GRP]
DCR_GRP_TYPE = DB
DCR_GRP_NAME = GRP_DSC
DCR_GRP_N_EP = 2
DCR_GRP_DSKCHK_CNT = 57
[GRP_DSC]
DCR_EP_NAME = DSC0
DCR_EP_SEQNO = 0
DCR_EP_PORT = 5238
[GRP_DSC]
DCR_EP_NAME = DSC1
DCR_EP_SEQNO = 1
DCR_EP_PORT = 5239


路径:/home/dmdba/dmdbms/dsc_config/dmasvrmal.ini
[MAL_INST0]
MAL_INST_NAME = ASM0
MAL_HOST = 192.168.126.144
MAL_PORT = 11266
[MAL_INST1]
MAL_INST_NAME = ASM1
MAL_HOST = 192.168.126.145
MAL_PORT = 11266


路径:/home/dmdba/dmdbms/dsc_config/dmdcr.ini
DMDCR_PATH = /dev/dm/asm-dmdcr
DMDCR_MAL_PATH = /home/dmdba/dmdbms/dsc_config/DSC0/dmasvrmal.ini
DMDCR_SEQNO = 0
DMDCR_AUTO_OPEN_CHECK = 111
DMDCR_ASM_TRACE_LEVEL = 2
## 集群稳定后可取消注释启用自动拉起
##DMDCR_ASM_RESTART_INTERVAL = 60
##DMDCR_ASM_STARTUP_CMD = /home/dmdba/dmdbms/dsc_config/DmAsmService_DSC0 start
##DMDCR_DB_RESTART_INTERVAL = 60
##DMDCR_DB_STARTUP_CMD = /home/dmdba/dmdbms/dsc_config/DmService_DSC0 start

路径:/home/dmdba/dmdbms/dsc_config/dmdcr.ini(与 DM2 不同,需单独写)
DMDCR_PATH = /dev/dm/asm-dmdcr
DMDCR_MAL_PATH = /home/dmdba/dmdbms/dsc_config/DSC1/dmasvrmal.ini
DMDCR_SEQNO = 1
DMDCR_AUTO_OPEN_CHECK = 111
DMDCR_ASM_TRACE_LEVEL = 2
## 集群稳定后可取消注释启用自动拉起
##DMDCR_ASM_RESTART_INTERVAL = 60
##DMDCR_ASM_STARTUP_CMD = /home/dmdba/dmdbms/dsc_config/DmAsmService_DSC1 start
##DMDCR_DB_RESTART_INTERVAL = 60
##DMDCR_DB_STARTUP_CMD = /home/dmdba/dmdbms/dsc_config/DmService_DSC1 start

路径:/home/dmdba/dmdbms/dsc_config/dminit.ini
DB_NAME = DSC
SYSDBA_PWD = Sysdba123.
SYSAUDITOR_PWD = Sysauditor123.
SYSTEM_PATH = +DMDATA/data
SYSTEM = +DMDATA/data/SYSTEM.dbf
SYSTEM_SIZE = 1024
ROLL = +DMDATA/data/ROLL.dbf
ROLL_SIZE = 10000
MAIN = +DMDATA/data/MAIN.dbf
MAIN_SIZE = 1024
CTL_PATH = +DMDATA/data/dm.ctl
CTL_SIZE = 8
LOG_SIZE = 2048
DCR_PATH = /dev/dm/asm-dmdcr
DCR_SEQNO = 0
AUTO_OVERWRITE = 1
PAGE_SIZE = 32
EXTENT_SIZE = 16
CASE_SENSITIVE = 0
BLANK_PAD_MODE = 1
[DSC0]
CONFIG_PATH = /home/dmdba/dmdbms/dsc_config/DSC0
PORT_NUM = 5238
MAL_HOST = 192.168.126.144
MAL_PORT = 11246
LOG_PATH = +DMLOG/DSC0_LOG01.log
LOG_PATH = +DMLOG/DSC0_LOG02.log
[DSC1]
CONFIG_PATH = /home/dmdba/dmdbms/dsc_config/DSC1
PORT_NUM = 5239
MAL_HOST = 192.168.126.145
MAL_PORT = 11246
LOG_PATH = +DMLOG/DSC1_LOG01.log
LOG_PATH = +DMLOG/DSC1_LOG02.log

路径:/home/dmdba/dmdbms/dsc_config/DSC0/dmarch.ini
ARCH_WAIT_APPLY = 0
[ARCHIVE_LOCAL1]
ARCH_TYPE = LOCAL
ARCH_DEST = +DMARCH/ARCH/DSC0/arch
ARCH_FILE_SIZE = 2048
ARCH_SPACE_LIMIT = 102400
[ARCHIVE_REMOTE1]
ARCH_TYPE = REMOTE
ARCH_DEST = DSC1
ARCH_INCOMING_PATH = +DMARCH/ARCH/DSC1/arch
ARCH_FILE_SIZE = 2048
ARCH_SPACE_LIMIT = 102400

路径:/home/dmdba/dmdbms/dsc_config/DSC1/dmarch.ini
ARCH_WAIT_APPLY = 0
[ARCHIVE_LOCAL1]
ARCH_TYPE = LOCAL
ARCH_DEST = +DMARCH/ARCH/DSC1/arch
ARCH_FILE_SIZE = 2048
ARCH_SPACE_LIMIT = 102400
[ARCHIVE_REMOTE1]
ARCH_TYPE = REMOTE
ARCH_DEST = DSC0
ARCH_INCOMING_PATH = +DMARCH/ARCH/DSC0/arch
ARCH_FILE_SIZE = 2048
ARCH_SPACE_LIMIT = 102400

路径:/home/dmdba/dmdbms/bin/dmcssm.ini
CSSM_OGUID = 210715
CSSM_CSS_IP = 192.168.126.144:11286
CSSM_CSS_IP = 192.168.126.145:11286
CSSM_LOG_PATH = ../log
CSSM_LOG_FILE_SIZE = 512
CSSM_LOG_SPACE_LIMIT = 2048


按以下顺序依次执行,严格区分在哪台机器、用哪个用户执行。
su - dmdba
cat > /home/dmdba/dmdbms/dsc_config/dmdcr_cfg.ini << 'EOF'
DCR_N_GRP = 3
DCR_VTD_PATH = /dev/dm/asm-dmvote
DCR_OGUID = 210715
[GRP]
DCR_GRP_TYPE = CSS
DCR_GRP_NAME = GRP_CSS
DCR_GRP_N_EP = 2
DCR_GRP_DSKCHK_CNT = 65
[GRP_CSS]
DCR_EP_NAME = CSS0
DCR_EP_HOST = 192.168.126.144
DCR_EP_PORT = 11286
[GRP_CSS]
DCR_EP_NAME = CSS1
DCR_EP_HOST = 192.168.126.145
DCR_EP_PORT = 11286
[GRP]
DCR_GRP_TYPE = ASM
DCR_GRP_NAME = GRP_ASM
DCR_GRP_N_EP = 2
DCR_GRP_DSKCHK_CNT = 61
[GRP_ASM]
DCR_EP_NAME = ASM0
DCR_EP_SHM_KEY = 42424
DCR_EP_SHM_SIZE = 1024
DCR_EP_HOST = 192.168.126.144
DCR_EP_PORT = 11276
DCR_EP_ASM_LOAD_PATH = /dev/dm
[GRP_ASM]
DCR_EP_NAME = ASM1
DCR_EP_SHM_KEY = 42425
DCR_EP_SHM_SIZE = 1024
DCR_EP_HOST = 192.168.126.145
DCR_EP_PORT = 11276
DCR_EP_ASM_LOAD_PATH = /dev/dm
[GRP]
DCR_GRP_TYPE = DB
DCR_GRP_NAME = GRP_DSC
DCR_GRP_N_EP = 2
DCR_GRP_DSKCHK_CNT = 57
[GRP_DSC]
DCR_EP_NAME = DSC0
DCR_EP_SEQNO = 0
DCR_EP_PORT = 5238
[GRP_DSC]
DCR_EP_NAME = DSC1
DCR_EP_SEQNO = 1
DCR_EP_PORT = 5239
EOF

cat > /home/dmdba/dmdbms/dsc_config/dminit.ini << 'EOF'
DB_NAME = DSC
SYSDBA_PWD = Sysdba123
SYSAUDITOR_PWD = Sysdba123
SYSTEM_PATH = +DMDATA/data
SYSTEM = +DMDATA/data/SYSTEM.dbf
SYSTEM_SIZE = 1024
ROLL = +DMDATA/data/ROLL.dbf
ROLL_SIZE = 10000
MAIN = +DMDATA/data/MAIN.dbf
MAIN_SIZE = 1024
CTL_PATH = +DMDATA/data/dm.ctl
CTL_SIZE = 8
LOG_SIZE = 2048
DCR_PATH = /dev/dm/asm-dmdcr
DCR_SEQNO = 0
AUTO_OVERWRITE = 1
PAGE_SIZE = 32
EXTENT_SIZE = 16
CASE_SENSITIVE = 0
BLANK_PAD_MODE = 1
[DSC0]
CONFIG_PATH = /home/dmdba/dmdbms/dsc_config/DSC0
PORT_NUM = 5236
MAL_HOST = 192.168.126.144
MAL_PORT = 11246
LOG_PATH = +DMLOG/DSC0_LOG01.log
LOG_PATH = +DMLOG/DSC0_LOG02.log
[DSC1]
CONFIG_PATH = /home/dmdba/dmdbms/dsc_config/DSC1
PORT_NUM = 5236
MAL_HOST = 192.168.126.145
MAL_PORT = 11246
LOG_PATH = +DMLOG/DSC1_LOG01.log
LOG_PATH = +DMLOG/DSC1_LOG02.log
EOF

cat > /home/dmdba/dmdbms/dsc_config/dmasvrmal.ini << 'EOF'
[MAL_INST0]
MAL_INST_NAME = ASM0
MAL_HOST = 192.168.126.144
MAL_PORT = 11266
[MAL_INST1]
MAL_INST_NAME = ASM1
MAL_HOST = 192.168.126.145
MAL_PORT = 11266
EOF

cp /home/dmdba/dmdbms/dsc_config/dmasvrmal.ini /home/dmdba/dmdbms/dsc_config/DSC0/
cp /home/dmdba/dmdbms/dsc_config/dmasvrmal.ini /home/dmdba/dmdbms/dsc_config/DSC1/
cat > /home/dmdba/dmdbms/dsc_config/dmdcr.ini << 'EOF'
DMDCR_PATH = /dev/dm/asm-dmdcr
DMDCR_MAL_PATH = /home/dmdba/dmdbms/dsc_config/DSC0/dmasvrmal.ini
DMDCR_SEQNO = 0
DMDCR_AUTO_OPEN_CHECK = 111
DMDCR_ASM_TRACE_LEVEL = 2
EOF

cat > /home/dmdba/dmdbms/dsc_config/DSC0/dmarch.ini << 'EOF'
ARCH_WAIT_APPLY = 0
[ARCHIVE_LOCAL1]
ARCH_TYPE = LOCAL
ARCH_DEST = +DMARCH/ARCH/DSC0/arch
ARCH_FILE_SIZE = 2048
ARCH_SPACE_LIMIT = 102400
[ARCHIVE_REMOTE1]
ARCH_TYPE = REMOTE
ARCH_DEST = DSC1
ARCH_INCOMING_PATH = +DMARCH/ARCH/DSC1/arch
ARCH_FILE_SIZE = 2048
ARCH_SPACE_LIMIT = 102400
EOF

cat > /home/dmdba/dmdbms/dsc_config/DSC1/dmarch.ini << 'EOF'
ARCH_WAIT_APPLY = 0
[ARCHIVE_LOCAL1]
ARCH_TYPE = LOCAL
ARCH_DEST = +DMARCH/ARCH/DSC1/arch
ARCH_FILE_SIZE = 2048
ARCH_SPACE_LIMIT = 102400
[ARCHIVE_REMOTE1]
ARCH_TYPE = REMOTE
ARCH_DEST = DSC0
ARCH_INCOMING_PATH = +DMARCH/ARCH/DSC0/arch
ARCH_FILE_SIZE = 2048
ARCH_SPACE_LIMIT = 102400
EOF

cat > /home/dmdba/dmdbms/bin/dmcssm.ini << 'EOF'
CSSM_OGUID = 210715
CSSM_CSS_IP = 192.168.126.144:11286
CSSM_CSS_IP = 192.168.126.145:11286
CSSM_LOG_PATH = ../log
CSSM_LOG_FILE_SIZE = 512
CSSM_LOG_SPACE_LIMIT = 2048
EOF

cd /home/dmdba/dmdbms/bin
./dmasmcmd << 'ASMSCRIPT'
create dcrdisk '/dev/dm/asm-dmdcr' 'dcr'
create votedisk '/dev/dm/asm-dmvote' 'vote'
init dcrdisk '/dev/dm/asm-dmdcr' from '/home/dmdba/dmdbms/dsc_config/dmdcr_cfg.ini' identified by 'Sysdba123.'
init votedisk '/dev/dm/asm-dmvote' from '/home/dmdba/dmdbms/dsc_config/dmdcr_cfg.ini'
create asmdisk '/dev/dm/asm-dmdata' 'DATA0'
create asmdisk '/dev/dm/asm-dmlog' 'LOG0'
create asmdisk '/dev/dm/asm-dmarch' 'ARCH0'
ASMSCRIPT
检查输出,确保所有步骤无报错。
# DM2 上(dmdba 用户)
scp /home/dmdba/dmdbms/dsc_config/dmdcr_cfg.ini dmdba@192.168.126.145:/home/dmdba/dmdbms/dsc_config/
scp /home/dmdba/dmdbms/dsc_config/dmasvrmal.ini dmdba@192.168.126.145:/home/dmdba/dmdbms/dsc_config/
scp /home/dmdba/dmdbms/dsc_config/dmdcr.ini dmdba@192.168.126.145:/home/dmdba/dmdbms/dsc_config/dmdcr.ini.tmp
scp /home/dmdba/dmdbms/dsc_config/dminit.ini dmdba@192.168.126.145:/home/dmdba/dmdbms/dsc_config/
scp /home/dmdba/dmdbms/bin/dmcssm.ini dmdba@192.168.126.145:/home/dmdba/dmdbms/bin/
# DM3 上修改 dmdcr.ini(dmdba 用户)
cp /home/dmdba/dmdbms/dsc_config/dmasvrmal.ini /home/dmdba/dmdbms/dsc_config/DSC1/
cat > /home/dmdba/dmdbms/dsc_config/dmdcr.ini << 'EOF'
DMDCR_PATH = /dev/dm/asm-dmdcr
DMDCR_MAL_PATH = /home/dmdba/dmdbms/dsc_config/DSC1/dmasvrmal.ini
DMDCR_SEQNO = 1
DMDCR_AUTO_OPEN_CHECK = 111
DMDCR_ASM_TRACE_LEVEL = 2
EOF

# DM2 和 DM3 都执行(dmdba 用户)
/home/dmdba/dmdbms/bin/dmcss DCR_INI=/home/dmdba/dmdbms/dsc_config/dmdcr.ini &
# DM2 和 DM3 都执行(dmdba 用户)
/home/dmdba/dmdbms/bin/dmasmsvr DCR_INI=/home/dmdba/dmdbms/dsc_config/dmdcr.ini &
# DM2 上(dmdba 用户)
/home/dmdba/dmdbms/bin/dmasmtool DCR_INI=/home/dmdba/dmdbms/dsc_config/dmdcr.ini << 'ASMSQL'
create diskgroup 'DMLOG' asmdisk '/dev/dm/asm-dmlog'
create diskgroup 'DMDATA' asmdisk '/dev/dm/asm-dmdata'
create diskgroup 'DMARCH' asmdisk '/dev/dm/asm-dmarch'
ASMSQL
# DM2 上(dmdba 用户)
/home/dmdba/dmdbms/bin/dminit control=/home/dmdba/dmdbms/dsc_config/dminit.ini
初始化完成后,
/home/dmdba/dmdbms/dsc_config/DSC1/下会生成 DM3 节点的配置文件。
将 DSC1 目录拷贝到 DM3:
scp -r /home/dmdba/dmdbms/dsc_config/DSC1/* dmdba@192.168.126.145:/home/dmdba/dmdbms/dsc_config/DSC1/
# DM2 上
echo "ARCH_INI = 1" >> /home/dmdba/dmdbms/dsc_config/DSC0/dm.ini
# DM3 上
echo "ARCH_INI = 1" >> /home/dmdba/dmdbms/dsc_config/DSC1/dm.ini
# DM2 上(dmdba 用户)
/home/dmdba/dmdbms/bin/dmserver /home/dmdba/dmdbms/dsc_config/DSC0/dm.ini dcr_ini=/home/dmdba/dmdbms/dsc_config/dmdcr.ini &
# DM3 上(dmdba 用户)
/home/dmdba/dmdbms/bin/dmserver /home/dmdba/dmdbms/dsc_config/DSC1/dm.ini dcr_ini=/home/dmdba/dmdbms/dsc_config/dmdcr.ini &
# 任意一台机器(dmdba 用户)
/home/dmdba/dmdbms/bin/dmcssm INI_PATH=/home/dmdba/dmdbms/bin/dmcssm.ini
进入监视器后执行:
show

集群运行正常后,在两台机器上注册服务(root 用户):
# ========== DM2 ==========
su root
cd /home/dmdba/dmdbms/script/root
./dm_service_installer.sh -t dmcss -dcr_ini /home/dmdba/dmdbms/dsc_config/dmdcr.ini -p CSS01
./dm_service_installer.sh -t dmasmsvr -dcr_ini /home/dmdba/dmdbms/dsc_config/dmdcr.ini -y DmCSSServiceCSS01.service -p ASM01
./dm_service_installer.sh -t dmserver -dm_ini /home/dmdba/dmdbms/dsc_config/DSC0/dm.ini -dcr_ini /home/dmdba/dmdbms/dsc_config/dmdcr.ini -y DmASMSvrServiceASM01.service -p DSC01
# ========== DM3 ==========
su root
cd /home/dmdba/dmdbms/script/root
./dm_service_installer.sh -t dmcss -dcr_ini /home/dmdba/dmdbms/dsc_config/dmdcr.ini -p CSS02
./dm_service_installer.sh -t dmasmsvr -dcr_ini /home/dmdba/dmdbms/dsc_config/dmdcr.ini -y DmCSSServiceCSS02.service -p ASM02
./dm_service_installer.sh -t dmserver -dm_ini /home/dmdba/dmdbms/dsc_config/DSC1/dm.ini -dcr_ini /home/dmdba/dmdbms/dsc_config/dmdcr.ini -y DmASMSvrServiceASM02.service -p DSC02



su root
cd /home/dmdba/dmdbms/script/root
./dm_service_installer.sh -t dmcssm -cssm_ini /home/dmdba/dmdbms/bin/dmcssm.ini -p DSCMonitor

# 两台机器都以 root 执行
setcap cap_net_raw,cap_net_admin=eip /home/dmdba/dmdbms/bin/dmserver
setcap cap_net_raw,cap_net_admin=eip /home/dmdba/dmdbms/bin/dmasmsvr
# 验证
getcap /home/dmdba/dmdbms/bin/dmserver
getcap /home/dmdba/dmdbms/bin/dmasmsvr
这是 Linux 的 capabilities 机制——在不给 root 权限的前提下,针对性地赋予二进制可执行文件两个网络特权。
DM DSC 集群的三个核心功能依赖这些权限:
CSS 心跳检测——不是简单 ping,而是通过 MAL 协议发的底层探测包。没 cap_net_raw,socket(PF_PACKET, SOCK_RAW) 直接返 EPERM
集群脑裂仲裁——需要实时判断对端是否宕机,依赖 raw socket 的低延迟
避免以 root 运行——如果不加 setcap,dmserver/dmasmsvr 必须以 root 启动才能拿到这些权限。用 root 跑数据库进程是安全红线(一旦被攻破,攻击者掌握整个 OS)
传统做法: root 身份启动 dmserver → 拥有全部权限 → 危险
setcap 做法: dmdba 身份启动 dmserver → 缺少 raw socket 权限 → 加 setcap 精确授予这两个权限 → 安全且可用


| 操作 | 命令(两台机器都要执行) |
|---|---|
| 启动集群 | DmCSSServiceCSS start(CSS 会自动拉起 ASM 和 DMSERVER) |
| 停止数据库 | DmServiceDSC stop |
| 停止 ASM | DmASMSvrServiceASM stop |
| 停止 CSS | DmCSSServiceCSS stop |
| 查看集群状态 | dmcssm INI_PATH=dmcssm.ini 然后 show |
**停止顺序严格:**DMSERVER → ASM → CSS(后两个要尽快停止,避免被 CSS 自动拉起)
| 问题 | 检查方法 |
|---|---|
| 共享磁盘不识别 | fdisk -l | grep /dev/sd 查看 |
| udev 未生效 | ls -la /dev/dm/asm-* 是否有软链接 |
| CSS 启动失败 | 查看日志 tail -f /home/dmdba/dmdbms/log/*.log |
| 端口不通 | telnet 对方IP 端口 测试 |
| 监视器连不上 | 确认 CSS 服务已启动,防火墙已关闭 |
DM 实例按配置分配共享内存(MEMORY_POOL/BUFFER),两个实例一起跑可能 OOM
OOM = Out of Memory(内存耗尽)
Linux 内核在物理内存 + swap 全部用尽时,会触发 OOM Killer,自动挑一个进程杀掉以释放内存。两个 DM 实例(旧的 DAMENG + 新的 DSC)各自占用 1-4GB 共享内存,如果虚拟机只分配了 4-6GB 内存,两个一起跑就容易触发 OOM。
DSC 集群首次启动时,ARCH_INI=1 会导致启动死锁:
DSC0 启动过程:
装载数据文件、控制文件
读 redo log,确定恢复起点
触犯检查点(checkpoint)——必须将本节点上次的归档状态同步给远程节点 DSC1
调用 remote arch flush 向 DSC1 发同步请求
DSC1 还没启动 → ret_code=-810(对端不可达)
checkpoint 失败 → 回到步骤 3 重试
DSC1 启动过程:
同样走装载 → checkpoint
同样向 DSC0 发同步请求
但 DSC0 正困在自己的死循环里,无法响应 DSC1 的请求
DSC1 也失败
结果:两端都在等对方,谁都无法到达 OPEN 状态。日志里就是在 DM2 看到的那一幕——checkpoint end(code:-810) 无限刷屏。
两个节点 OPEN 之后,彼此的监听端口和内部通信信道已经就绪。此时 remote arch flush 是正常工作的,不会再报 -810。
① 两台 dmserver 启动 → 各自 OPEN
② echo “ARCH_INI = 1” >> dm.ini
③ 依次重启 dmserver(先 DSC0 后 DSC1)
这不是 DM 特有 bug,大多数多节点数据库(Oracle RAC、PostgreSQL 流复制)在首次建库后都不该启用跨节点归档——节点还没彼此认识,归档同步必然失败。
知识问答环节
问:CSS ASM DMSERVER三个的作用都是什么?
答:三者形成严格的下→上依赖链,每层职责互不重叠:
做什么:管理节点存活状态、脑裂仲裁、集群拓扑。
每秒向对端 CSS 发心跳包,确认对方还活着
节点宕机时执行脑裂仲裁:只有拿到多数表决票的节点存活
管理所有 EP(Endpoint)的启停——ASM 和 DMSERVER 的加入/退出都要通过 CSS 注册
类比:小区门口的保安系统——监控谁进出、发现门锁坏了就报警。
做什么:操作共享磁盘的 I/O,不处理 SQL。
管理磁盘组(diskgroup)和盘区(extent)分配
所有数据文件的读写——DMSERVER 不直接碰磁盘,全部委托给 ASM
保证两个节点的 DMSERVER 看到的磁盘数据一致(分布式锁、缓存同步)
类比:写字楼的物业——管水电、管电梯、管维护。写字楼里的公司(DMSERVER)只管自己的业务,不用管大楼怎么运转。
做什么:处理 SQL、管理事务、写 redo log、做检查点。
接收客户端连接,解析 SQL
执行事务(ACID 保证),生成 redo log
检查点(ckpt)协调——这也是你之前遇到 -810 的原因:DSC0 做检查点要和对端 DSC1 同步,对端不在就死循环
一切数据读写通过 ASM 代理,不直接操作磁盘
类比:写字楼里的公司——管自己的业务。水电网交给物业(ASM),安保交给保安(CSS)。
启动顺序和关闭顺序是什么?
第①步 两台同时启动 CSS → /home/dmdba/dmdbms/bin/dmcss ...
第②步 两台同时启动 ASM → /home/dmdba/dmdbms/bin/dmasmsvr ...
第③步 两台同时启动 DMSERVER → /home/dmdba/dmdbms/bin/dmserver ...
CSS 是底层集群通信底座;ASM 依赖 CSS;DMSERVER 依赖 ASM。下层没起,上层必败。
第①步 两台同时关闭 DMSERVER
第②步 两台同时关闭 ASM ← 这一步要快!CSS 会自动尝试拉起 ASM
第③步 两台同时关闭 CSS ← 同上,CSS 会尝试拉起 ASM 和 DMSERVER
启动:底层先起,上层后起。
关闭:倒序关,且 ASM/CSS 两步要快——CSS 有自动拉起机制,关慢了它会把刚关掉的又拉起来。
问:那关闭的时候可以直接关闭CSS吗 因为CSS会自己拉起来ASM和DMSERVER 为了避免ASM和DMSERVER关闭的时候被拉起来 可以先把CSS关闭吗
答:不能。 反过来关会出问题:
如果 CSS 先死:
ASM 和 DMSERVER 失去集群通信层,检测到 CSS 断开后各自独立触发容错逻辑
ASM 判定"CSS 故障 → 集群分裂",进入保护模式
DMSERVER 判定"集群隔离",可能触发实例自杀
两个节点各自试图做脑裂恢复,可能写脏数据到共享磁盘
问:DSC集群额CSS和主备集群的dmwatcher的作用好像一样 是吗?
答:职责有重叠,但机制完全不同。 可以说 dmwatcher 是"监视两个独立仓库的保安",CSS 是"两个工人共用一张桌子的协调员"。
***CSS:***两个厨师共用一张操作台。CSS 的工作:
正常时:协调两人不同时碰同一根菜——通过锁机制保证并发安全
一个人晕倒了:CSS 检测到晕倒,把晕倒那个人的工位锁掉(防止他突然醒来抢刀),让醒着的人继续切菜
如果两人都觉得自己醒着但实际已经无法通信了(脑裂):CSS 通过表决磁盘(VOTE disk)投票,只保留一人的操作权限,把另一个强制踢出
节点故障 → CSS 驱逐故障节点 → 存活节点接管全部工作
↑
被踢出去的是故障方,不是幸存方
***dmwatcher:***两个厨房各有一张操作台。dmwatcher 盯着主厨在做菜,把每一步操作步骤实时传给备用厨房,主厨晕倒了立刻让备用厨师穿围裙。
心跳检测、故障发现这两件事它们都做——这是所有集群管理器的共性。但 CSS 的核心难题是共享存储的并发控制,dmwatcher 的核心难题是redo 日志的可靠传输。问题域完全不同。
https://eco.dameng.com
文章
阅读量
获赞
