集群接管与资源配置(SAPHanaSR 经典版)

更新时间:
复制 MD 格式

重要

适用版本(执行前请确认)

  • 操作系统:SLES for SAP Applications 15 系列(SUSE 官方经典版指南适用于 15 SP1 或更新版本,无 angi 的 15 SP4 门槛;更早的 SLES for SAP 版本亦在经典版支持范围内,本系列基线为 SLES for SAP 15);

  • SAP HANA:SAP HANA 2.0 SPS05 rev59 及以上——本文配置的 Hook 组合(SAPHanaSR.py / susTkOver.py / susChkSrv.py)的要求(HANA 1.0 不提供 Python3 与多目标感知的 srConnectionChanged 参数);经典版资源代理兼容范围宽于 angi,可支持较早的 HANA 版本(《选型与决策指引》1.2 节)。

若环境同时满足 angi 的更高门槛(SLES for SAP 15 SP4 及以上、SAP HANA 2.0 SPS05 rev59.04 及以上),新部署建议优先选择 angi(见《选型与决策指引》1.3 节)。若环境低于上述 Hook 门槛(SAP HANA 2.0 SPS05 rev.059 以下,含 HANA 1.0),本文的 Hook 组合无法配置——请按《不满足 Hook 版本门槛时的方案与限制》以无 Hook 轮询模式运行,并按其第 5 章规划升级;资源定义等其余步骤不受影响。

本文档承接《SAP HANA HSR 配置》完成后的环境:HSR 复制关系已建立并通过手动接管测试验证,但 HANA 实例仍由人工管理,尚未由集群接管。本阶段完成 HA/DR Hook 配置与 Pacemaker 集群资源定义,由集群接管 HANA 实例的启动、停止、监控与故障接管。

后续路径:第 2 章配置与实例状态联动的 HA/DR Hook 脚本;第 3 章定义集群资源(含与《集群初始化》选型一致的 STONITH 方案 A/B 变体),并由集群接管实例;第 4 章验证故障接管与受控切换;第 5 章说明关键参数。若《选型与决策指引》选定的是 SAPHanaSR-angi,请转入《集群接管与资源配置(SAPHanaSR-angi)》。

开始前的检查

  • 集群已初始化、STONITH 已配置且隔离能力已验证(《集群初始化》第 1~3 章);

  • HSR 已建立并验证(《SAP HANA HSR 配置》第 1 章),且已完成集群接管前的手动接管测试、主备角色已恢复为初始状态:hana01 为主库(SiteA)、hana02 为备库(SiteB)(《SAP HANA HSR 配置》第 2 章);副本状态为同步(SOK);

  • 两节点已安装经典版 SAPHanaSR 资源代理包、未安装 SAPHanaSR-angi 包(《前置准备》6.2 节);本文配置的 Hook 组合(SAPHanaSR.py / susTkOver.py / susChkSrv.py)要求 SAP HANA 2.0 SPS05 rev59 及以上(《选型与决策指引》1.3 节);

  • 两节点 SAP HANA 实例的系统级自启动保持关闭(《前置准备》第 1 章)——systemd 风格下 saphostagent.service 与 SAP<SID>_<INO>.service 保持 enabled,自启动关闭由实例 profile 的 Autostart = 0 实现;集群接管后实例启停由集群统一控制。

说明
  • 本文档中:<SID> 表示大写 SAP 系统 ID(如 HA1),对应小写形式记作 <sid>(如 ha1);<INO> 表示两位实例号(如 10)。例如 SID=HA1、实例号=10 时,资源 msl_SAPHana_<SID>_HDB<INO> 即 msl_SAPHana_HA1_HDB10。

  • 站点名沿用 SiteA(hana01)与 SiteB(hana02);VIP 沿用《Infra 选型》4.2 节规划值(10.0.100.20,虚拟主机名 vhanadb)。

  • 命令用户约定:HANA 命令以 <sid>adm 执行;集群命令(crm、cs_wait_for_idle 等)以 root 执行;Hook 检查命令在 <sid>adm 的 cdtrace 环境中执行。

  • 第 2 章的 Hook 配置与 sudoers 需在两个节点分别执行。本系列 Scale-Up 部署的文件系统均为节点本地盘(《Infra 选型》3.2 节),global.ini 位于各节点本地路径 /hana/shared/<SID>/global/hdb/custom/config/global.ini。

  • 经典版与 angi 的配置不得混用(Hook 脚本路径、资源代理、命名与角色均不同,对比见《选型与决策指引》1.2 节);本文档全程使用经典版口径,如另一篇《集群接管与资源配置(SAPHanaSR-angi)》已执行,请勿重复配置。


1. 前置条件

本节确认集群与 HSR 均处于可接管状态:

# 集群状态(root,任一节点):两节点 online、无失败资源;STONITH 已配置
crm status

# HSR 复制状态(<sid>adm,主库节点 hana01):应为 ACTIVE
HDBSettings.sh systemReplicationStatus.py --sapcontrol=1
# overall_replication_status=ACTIVE

# 资源代理包(root,两个节点):应输出经典版 SAPHanaSR 包,且无 angi 包
rpm -qa | grep SAPHanaSR

# Hook 脚本存在性(root,两个节点):应包含 SAPHanaSR.py、susTkOver.py、susChkSrv.py(及 susCostOpt.py)
ls /usr/share/SAPHanaSR/

# SAP 服务状态(root,两个节点):saphostagent 与实例服务保持 enabled(systemd 风格)
systemctl list-unit-files | grep -E "saphostagent|SAP<SID>_<INO>"
# 预期 saphostagent.service enabled、SAP<SID>_<INO>.service enabled

# 实例自启动已关闭(<sid>adm,两个节点):实例 profile 中 Autostart = 0
grep -i 'Autostart' /usr/sap/<SID>/SYS/profile/<SID>_HDB<INO>_<hostname>
# 预期 Autostart = 0

同时确认:

  • 操作模式已在两个节点检查完毕([system_replication] operation_mode = logreplay,见《SAP HANA HSR 配置》1.6 节);

  • Cost Optimized 场景:备库的内存限制与表预加载设置已完成(《SAP HANA HSR 配置》1.4 节),本章 2.5 节与 3.6 节还需追加 Hook 与非复制实例配置。


2. HA/DR Hook 配置

2.1 Hook 脚本概述

SAPHanaSR 经典版通过 SAP HANA 的 HA/DR provider 接口实现集群联动。需要配置的 Hook 脚本均随 SAPHanaSR 包提供,位于 /usr/share/SAPHanaSR/:

Hook 脚本

HA/DR 方法

作用

必要性

SAPHanaSR.py

srConnectionChanged()

复制连接状态变化(同步/失去同步)时立即写入集群属性

必需(SUSE 官方经典版指南)

susTkOver.py

preTakeover()

阻止集群正常运行期间的手动接管;仅在多状态资源处于维护模式或集群停止时放行

推荐

susChkSrv.py

srServiceStateChanged()

indexserver 进程故障时加速接管(官方指南起点:action_on_lost=stop,即停止实例交由集群处理)

推荐

susCostOpt.py

postTakeover()

Cost Optimized 专用:接管后解除新主库内存限制、恢复表预加载

仅 Cost Optimized(仅备库,见 2.5 节)

说明
  • Hook 脚本必须直接使用包内文件,不要拷贝或移动——脚本被移动或拷贝后,SUSE 包的常规更新将不会生效。

  • 修改 global.ini 需要先停止 HANA,使 HANA 在启动时加载 Hook;也可使用 SAPHanaSR-manageProvider 在不停机的情况下管理 provider 段(以 <sid>adm 运行,--reconfigure 等效于 hdbnsutil -reloadHADRProviders),详见 manpage SAPHanaSR-manageProvider(8)。本文按停库修改文件的常规流程撰写。

2.2 修改 global.ini(两个节点)

步骤 1:停止两个节点的 HANA

# 分别在 hana01、hana02 以 <sid>adm 执行
sapcontrol -nr <INO> -function StopSystem

步骤 2:在两个节点分别编辑各自的 global.ini(路径 /hana/shared/<SID>/global/hdb/custom/config/global.ini),添加以下三个 provider 段:

[ha_dr_provider_saphanasr]
provider = SAPHanaSR
path = /usr/share/SAPHanaSR/
execution_order = 1

[ha_dr_provider_sustkover]
provider = susTkOver
path = /usr/share/SAPHanaSR/
execution_order = 2

[ha_dr_provider_suschksrv]
provider = susChkSrv
path = /usr/share/SAPHanaSR/
execution_order = 3
action_on_lost = stop

[trace]
ha_dr_saphanasr = info
ha_dr_sustkover = info
ha_dr_suschksrv = info

各段说明:

  • SAPHanaSR 无需任何配置参数;execution_order 决定多个 provider 的执行顺序(本文按 1/2/3 设置)。

  • susTkOver 通常无需调整配置;超时参数 sustkover_timeout 默认 30 秒,适用于大多数环境。

  • susChkSrv 采用渐进式配置:官方指南给出的起点为 action_on_lost = stop——indexserver 进程丢失时执行 sapcontrol ... StopSystem 停止实例,使集群尽快检测到故障并按接管策略处理(相比放任 HANA 原地重启可加速接管)。其他可选动作为 ignore(默认,仅记录)、kill(HDB kill-<信号>)、fence(需 STONITH 与额外 sudo 权限);任何调优应与 SAP 专家确认。

  • 若 global.ini 中已存在 [trace] 段,将上述 trace 行合并进已有段即可,不要重复定义同名段。

  • Cost Optimized 场景还需按 2.5 节在备库添加 susCostOpt 段——请在本步骤停库期间一并完成,避免再次停机。

说明

若 action_on_lost = stop 与资源参数 AUTOMATED_REGISTER=true 组合使用,需由 HANA 在自动注册前释放全部 OS 资源(官方要求,见 manpage susChkSrv.py(7));初始配置保持 AUTOMATED_REGISTER=false 时无此顾虑。

2.3 配置 sudo 权限(两个节点)

Hook 脚本以 <sid>adm 运行,并使用 sudo 访问集群属性与辅助命令。<sid>adm 用户必须能设置 hana_<sid>_site_srHook_* 集群属性且免密码。以下条目写入新文件 /etc/sudoers.d/SAPHanaSR(无需编辑原 /etc/sudoers):

基础版(权限范围最小化,满足全部 Hook 需要):

# SAPHanaSR-ScaleUp entries for writing srHook cluster attribute and SAPHanaSR-hookHelper
<sid>adm ALL=(ALL) NOPASSWD: /usr/sbin/crm_attribute -n hana_<sid>_site_srHook_*
<sid>adm ALL=(ALL) NOPASSWD: /usr/sbin/SAPHanaSR-hookHelper *

高安全级别版(逐命令限定):

# SAPHanaSR-ScaleUp entries for writing srHook cluster attribute
Cmnd_Alias SOK_SITEA    = /usr/sbin/crm_attribute -n hana_<sid>_site_srHook_SiteA -v SOK   -t crm_config -s SAPHanaSR
Cmnd_Alias SFAIL_SITEA  = /usr/sbin/crm_attribute -n hana_<sid>_site_srHook_SiteA -v SFAIL -t crm_config -s SAPHanaSR
Cmnd_Alias SOK_SITEB    = /usr/sbin/crm_attribute -n hana_<sid>_site_srHook_SiteB -v SOK   -t crm_config -s SAPHanaSR
Cmnd_Alias SFAIL_SITEB  = /usr/sbin/crm_attribute -n hana_<sid>_site_srHook_SiteB -v SFAIL -t crm_config -s SAPHanaSR
Cmnd_Alias HOOK_HELPER  = /usr/sbin/SAPHanaSR-hookHelper --sid=<SID> --case=checkTakeover

<sid>adm ALL=(ALL) NOPASSWD: SOK_SITEA, SFAIL_SITEA, SOK_SITEB, SFAIL_SITEB, HOOK_HELPER
说明
  • 将 <sid> 替换为小写 SID(如 ha1)、<SID> 替换为大写 SID;站点名使用实际站点名(本例 SiteA/SiteB)。

  • 上述路径为经典版路径:辅助脚本位于 /usr/sbin/SAPHanaSR-hookHelper(angi 版为 /usr/bin/),基础版条目按官方经典版指南的写法限定到 site_srHook 属性。

  • 高安全版中每条 Cmnd_Alias 必须是单行,别名标识符必须为大写。本文 2.2 节设置的 action_on_lost=stop 不需要 fenceMe 权限;若后续将 susChkSrv 调整为 fence(须经 SAP 专家确认并具备 STONITH 方法),需同步追加 /usr/sbin/SAPHanaSR-hookHelper --sid=<SID> --case=fenceMe 的 sudo 条目。

  • 文件创建后建议用 visudo -cf /etc/sudoers.d/SAPHanaSR 校验语法;确认无报错后检查文件权限为 0440。

2.4 启动 HANA 并验证 Hook 加载

# 分别在 hana01、hana02 以 <sid>adm 启动
HDB start

启动后以 <sid>adm 检查各 Hook 是否加载并初始化成功:

cdtrace

# SAPHanaSR
grep HADR.*load.*SAPHanaSR nameserver_*.trc
grep SAPHanaSR.init nameserver_*.trc

# susTkOver
grep HADR.*load.*susTkOver nameserver_*.trc
grep susTkOver.init nameserver_*.trc

# susChkSrv
grep HADR.*load.*susChkSrv nameserver_*.trc
grep susChkSrv.init nameserver_*.trc
egrep '(LOST:|STOP:|START:|DOWN:|init|load|fail)' nameserver_suschksrv.trc

事件级验证命令(在对应事件发生后才会有输出,配合第 4 章测试使用):

# SAPHanaSR 是否成功与集群交互(或落盘 fallback 文件)
grep SAPHanaSR.srConnection.*CRM nameserver_*.trc
grep SAPHanaSR.srConnection.*fallback nameserver_*.trc

# susTkOver 放行/阻止手动接管
grep susTkOver.preTakeover.*permit nameserver_*.trc
grep susTkOver.preTakeover.*failed.*50277 nameserver_*.trc

# susChkSrv 的 indexserver 故障动作(action_on_lost=stop 时)
grep susChkSrv.*srServiceStateChanged nameserver_*.trc
grep -C2 Executed.*StopSystem nameserver_*.trc

# sudo 权限是否生效(root)
grep "sudo.*SAPHanaSR-hookHelper" /var/log/messages

全部 Hook 加载无误后,继续第 3 章的集群资源配置。

2.5 仅 Cost Optimized:susCostOpt 与 keystore

Cost Optimized 场景中,备库配置了内存限制并关闭了表预加载(《SAP HANA HSR 配置》1.4 节)。接管发生时,susCostOpt.py 的 postTakeover() 方法通过 SQL 解除新主库的内存分配限制,并恢复表预加载。

配置位置:该 Hook 仅需配置在备库节点(本例 hana02)。在 2.2 节停库期间,将以下段追加到 hana02 的 global.ini:

[ha_dr_provider_suscostopt]
provider = susCostOpt
path = /usr/share/SAPHanaSR/
userkey = saphanasr_<SID>_costopt
execution_order = 2

[trace]
ha_dr_suscostopt = info
  • execution_order = 2 为强制要求——该 Hook 必须晚于 SAPHanaSR.py 运行;

  • userkey(可省略):数据库用户密钥在 <sid>adm keystore 中的名称,默认为 saphanasr_<SID>_costopt;

  • 可选参数 costopt_primary_global_allocation_limit = <limit-in-mb>:接管后为新主库设置的 global_allocation_limit(MB)。不设置或设置为 0 表示不限制(不设置时 Hook 执行 UNSET 语句解除限制)。

创建数据库用户密钥(hana02 以 <sid>adm 执行):

hdbuserstore SET saphanasr_<SID>_costopt localhost:3<INO>13 SYSTEM <password>
hdbuserstore LIST saphanasr_<SID>_costopt
重要

示例使用 SYSTEM 用户仅为演示。生产环境必须创建仅具备修改内存限制与表预加载权限的专用数据库用户,并将其加入 <sid>adm 的 keystore。用户密钥只需创建在备库节点。

验证(hana02 以 <sid>adm):

cdtrace
grep HADR.*load.*susCostOpt nameserver_*.trc
grep susCostOpt.init nameserver_*.trc

# 发生接管事件后确认 postTakeover 已执行
grep susCostOpt.*postTakeover nameserver_*.trc
说明
  • postTakeover() 方法要求 SAP HANA 2.0 SPS04 及以上;仅支持 Scale-Up;

  • 不得为 postTakeover() 方法配置其他 Hook,但本系列配置的其他方法(SAPHanaSR/susTkOver/susChkSrv)可与其并行使用;

  • postTakeover() 会同时修改 HANA 的内存配置与持久化配置(global.ini),接管后如需将角色回退到原始状态,须按恢复流程操作——概要见第 5 章 5.2 节,完整步骤见 manpage susCostOpt.py(7)。


3. 集群资源配置

3.1 加载方式与命名约定

本章给出 SAPHanaSR 经典版的完整集群资源配置脚本。推荐将 3.2 节脚本保存为本地文件(如 /root/crm-classic.txt,替换其中所有 <...> 占位符),然后加载到集群:

# 在任一集群节点以 root 执行
crm configure load update /root/crm-classic.txt
  • load update 为增量更新:只新增/修改脚本中出现的对象,未在脚本中出现的其他对象不受影响;重复加载为幂等更新。

  • 脚本中的「集群全局属性」与「STONITH」两段与《集群初始化》保持一致——按《Infra 选型》第 6 章的选型:方案 A(fence_aliyun)直接使用 3.2 节脚本;方案 B(SBD)请按 3.3 节替换对应两段。

  • 经典版的资源命名沿用官方模板:多状态资源为 msl_SAPHana_<SID>_HDB<INO>(ms 类型,Master/Slave 角色);顺序约束名为 ord_SAPHana_<SID>_HDB<INO>(与 angi 篇的 ord_saphana_... 大小写不同,请按本篇执行)。

3.2 完整集群资源配置脚本(方案 A 变体)

# vi crm-classic.txt
# ============================================================
# SAP HANA 集群资源配置 — SAPHanaSR 经典版(SID=<SID>,实例号=<INO>)
# 加载前请替换所有 <...> 占位符
# ============================================================

# === 集群全局属性与默认值(与《集群初始化》一致) ===
property cib-bootstrap-options: \
    stonith-enabled="true" \
    stonith-action="reboot" \
    stonith-timeout="150"
rsc_defaults rsc-options: \
    resource-stickiness="1000" \
    migration-threshold="5000"
op_defaults op-options: \
    timeout="600" \
    record-pending=true

# === STONITH(方案 A:fence_aliyun;方案 B 见 3.3 节替换块) ===
# 与《集群初始化》1.2 节完全相同
primitive res_ALIYUN_STONITH_1 stonith:fence_aliyun \
        op monitor interval=120 timeout=60 \
        params filter="InstanceIds=[\"<ECS Id1>\", \"<ECS Id2>\"]" plug=<ECS Id1> ram_role=SAP-HA-ROLE region=<region ID> \
        meta target-role=Started

primitive res_ALIYUN_STONITH_2 stonith:fence_aliyun \
        op monitor interval=120 timeout=60 \
        params filter="InstanceIds=[\"<ECS Id1>\", \"<ECS Id2>\"]" plug=<ECS Id2> ram_role=SAP-HA-ROLE region=<region ID> \
        meta target-role=Started

# STONITH位置约束:节点不运行自己的STONITH资源
location loc_stonith1_not_on_hana01 res_ALIYUN_STONITH_1 -inf: hana01
location loc_stonith2_not_on_hana02 res_ALIYUN_STONITH_2 -inf: hana02

# === SAPHanaTopology(收集并发布 HANA 拓扑与复制状态) ===
primitive rsc_SAPHanaTop_<SID>_HDB<INO> ocf:suse:SAPHanaTopology \
    op monitor interval=10 timeout=600 \
    op start interval=0 timeout=600 \
    op stop interval=0 timeout=300 \
    params SID=<SID> InstanceNumber=<INO>
clone cln_SAPHanaTop_<SID>_HDB<INO> rsc_SAPHanaTop_<SID>_HDB<INO> \
    meta clone-node-max=1 interleave=true

# === SAPHana(主备实例控制与接管决策;以维护状态加载,3.5 节激活) ===
primitive rsc_SAPHana_<SID>_HDB<INO> ocf:suse:SAPHana \
    op start interval=0 timeout=3600 \
    op stop interval=0 timeout=600 \
    op promote interval=0 timeout=900 \
    op monitor interval=60 role=Master timeout=700 \
    op monitor interval=61 role=Slave timeout=700 \
    params SID=<SID> InstanceNumber=<INO> PREFER_SITE_TAKEOVER=true \
        DUPLICATE_PRIMARY_TIMEOUT=7200 AUTOMATED_REGISTER=false \
    meta priority=100
ms msl_SAPHana_<SID>_HDB<INO> rsc_SAPHana_<SID>_HDB<INO> \
    meta clone-max=2 clone-node-max=1 interleave=true maintenance=true

# === 虚拟IP(阿里云 vpc-move-ip;SAP 应用通过 vhanadb 连接主库) ===
# routing_table 参数的值为 ECS 所在 VPC 对应的默认路由表 ID
primitive rsc_ip_<SID>_HDB<INO> ocf:aliyun:vpc-move-ip \
    params address=10.0.100.20 \
           routing_table=<routing-table-id> \
           endpoint=vpc-vpc.<region-id>.aliyuncs.com \
           interface=eth0 \
    op monitor interval=10s timeout=20s

# === 约束 ===
# VIP 跟随 Master(主库)
colocation col_saphana_ip_<SID>_HDB<INO> 2000: rsc_ip_<SID>_HDB<INO>:Started \
    msl_SAPHana_<SID>_HDB<INO>:Master
# Topology 先于 SAPHana 启动
order ord_SAPHana_<SID>_HDB<INO> Optional: cln_SAPHanaTop_<SID>_HDB<INO> \
    msl_SAPHana_<SID>_HDB<INO>
说明
  • Cost Optimized 场景:将参数 PREFER_SITE_TAKEOVER=true 改为 false(理由见 5.1 节),并在加载本脚本后按 3.6 节追加非复制实例资源与约束。

  • 为增加加载过程的安全性,可先执行 crm configure property maintenance-mode=true,加载完成后再执行 crm configure property maintenance-mode=false(SAPHana 多状态资源自身带有 maintenance=true,在 3.5 节激活前不会对实例执行任何操作)。

  • 官方经典版模板中 SAPHanaTopology 的监控间隔为 10s(angi 模板为 50s),SAPHana 的资源名、角色与操作超时也与 angi 不同;两代模板的示例值请勿交叉混用,按各自篇章执行。

  • 经典版资源集不含文件系统监控资源(SAPHanaFilesystem 为 angi 独有);/hana/shared 等文件系统的可用性由《前置准备》第 2 章的挂载配置保障。

3.3 方案 B(SBD)替换块

若《集群初始化》第 2 章采用方案 B(SBD),将 3.2 节脚本中的两段内容替换如下(其余部分保持不变):

  1. 「集群全局属性」段的 property 行替换为:

# === 集群全局属性(方案 B)===
property cib-bootstrap-options: \
    stonith-enabled="true" \
    stonith-action="reboot" \
    stonith-timeout="150" \
    priority-fencing-delay="60"

(rsc_defaults、op_defaults 两段保持不变。)

  1. 「STONITH」段(两个 fence_aliyun 资源与两条位置约束)整体替换为:

# === STONITH资源(SBD) ===
primitive stonith-sbd stonith:external/sbd \
    params pcmk_delay_max="30s"

SBD 资源无需位置约束——它由所有节点共同参与,不存在「节点隔离自己」的问题。相关超时参数取值与约束关系见《集群初始化》2.2 节。

与《集群初始化》的关系:按《集群初始化》2.1 节(ha-cluster-init -s)初始化的集群已创建同名的 stonith-sbd 资源;load update 按对象 ID 就地更新,不会产生第二个 STONITH 资源。本段加载后实际生效的变化是把 stonith-timeout 从初始化自动值(83s)统一为 150s;pcmk_delay_max、priority-fencing-delay 已在初始化时自动配置(取值一致)。若按《集群初始化》2.3 节手动配置,则为幂等重复加载。

3.4 资源与约束说明

资源 / 对象

作用

关键说明

res_ALIYUN_STONITH_1/2 + location(方案 A)/ stonith-sbd(方案 B)

节点隔离

与《集群初始化》配置相同,重复加载为幂等更新;位置约束保证节点不隔离自己(方案 A)

rsc_SAPHanaTop_<SID>_HDB<INO> + clone

收集 HANA 拓扑、复制与站点状态,写入集群属性供其他组件使用

两节点均运行

rsc_SAPHana_<SID>_HDB<INO> + ms

控制主备实例的启动/停止/提升/降级与接管决策(Master/Slave 角色)

以 maintenance=true 加载,3.5 节激活;参数说明见第 5 章

rsc_ip_<SID>_HDB<INO>

主库虚拟 IP(vhanadb),随主库漂移

阿里云上通过 VPC 路由表实现(Overlay IP);启动时创建 <VIP>/32 路由,漂移时改写路由

col_saphana_ip_<SID>_HDB<INO> / ord_SAPHana_<SID>_HDB<INO>

VIP 跟随 Master;Topology 先于 SAPHana 启动

顺序约束为可选(Optional),不阻塞其他资源

说明

经典版的主备角色在集群中表现为 Master/Slave(ms 多状态资源);angi 版为 Promoted/Unpromoted(clone ... promotable=true)。两代的资源对象名与角色名不同,配置请勿混用(对比见《选型与决策指引》1.2 节)。

3.5 激活多状态资源(集群接管)

SAPHana 多状态资源以 meta maintenance=true 加载,在激活前不会对 HANA 执行任何操作。按以下顺序激活(任一节点以 root 执行):

crm resource refresh msl_SAPHana_<SID>_HDB<INO>
cs_wait_for_idle -s 5
crm resource maintenance msl_SAPHana_<SID>_HDB<INO> off
  • crm resource refresh:让集群重新探测多状态资源状态(丢弃历史角色信息);

  • cs_wait_for_idle -s 5:等待集群进入空闲状态(ClusterTools2 包提供,已在《前置准备》6.1 节安装);

  • crm resource maintenance ... off:退出维护状态,集群开始接管实例——正常情况下 hana01 成为 Master(主库)、hana02 为 Slave(备库),VIP 在 hana01 上启动。

激活完成后进入第 4 章,使用 crm status 与 SAPHanaSR-showAttr 确认接管状态。

3.6 仅 Cost Optimized:非复制实例的集群资源

Cost Optimized 场景下,hana02 同时运行一个非复制的 HANA 实例(如 DEV/TST/QAS 系统)。为避免接管时两个实例争抢节点内存,集群必须在提升备库为主库之前自动关闭该非复制实例——这由 SAPInstance 资源代理与反亲和约束实现(经典版同为 ocf:heartbeat:SAPInstance,通过 sapstartsrv API 管理)。

将以下内容保存为 /root/crm-costopt.txt(<NPSID> 为非复制实例的 SID、<NPINO> 为其实例号;该实例运行在 hana02),在 3.2/3.3 节脚本加载后追加加载:

# vi crm-costopt.txt
# === 非复制实例资源(通过 sapstartsrv API 管理,无需 secure store 配置) ===
primitive rsc_SAP_<NPSID>_HDB<NPINO> ocf:heartbeat:SAPInstance \
    params InstanceName="<NPSID>_HDB<NPINO>_hana02" \
        MONITOR_SERVICES="hdbindexserver|hdbnameserver" \
        START_PROFILE="/usr/sap/<NPSID>/SYS/profile/<NPSID>_HDB<NPINO>_hana02" \
    op start interval=0 timeout=600 \
    op monitor interval=120 timeout=700 \
    op stop interval=0 timeout=300

# === 非复制实例的反亲和与联动约束 ===
# 非复制实例固定运行在 hana02,不允许在 hana01 上运行
location loc_<NPSID>_never_on_hana01 rsc_SAP_<NPSID>_HDB<NPINO> -inf: hana01
# 非复制实例不得与已提升的主库同节点
location loc_<NPSID>_never_on_promoted_node \
    rsc_SAP_<NPSID>_HDB<NPINO> rule -inf: hana_<SID>_clone_state eq PROMOTED
# 非复制实例不得与主库 VIP 同节点
colocation col_<NPSID>_never_with_<SID>_ip -inf: rsc_SAP_<NPSID>_HDB<NPINO>:Started \
    rsc_ip_<SID>_HDB<INO>
# 接管顺序:先优雅停止非复制实例,再提升备库
order ord_<NPSID>_stop_before_<SID>_promote mandatory: rsc_SAP_<NPSID>_HDB<NPINO>:stop \
    msl_SAPHana_<SID>_HDB<INO>:promote
# 在任一集群节点以 root 执行
crm configure load update /root/crm-costopt.txt
说明
  • 运行效果:正常情况下非复制实例运行在 hana02(备库节点);当生产主库被提升到 hana02 时(接管场景),非复制实例先被优雅停止(order 为 mandatory),随后备库才提升为主库;主备角色恢复后,再由管理员按需启动非复制实例。

  • 接管过程因需优雅停止非复制实例、且新主库表无预加载而耗时更长,这是 Cost Optimized 场景为节省资源付出的代价(因此建议 PREFER_SITE_TAKEOVER=false 优先本地重启,见 5.1 节)。

  • 非复制实例的系统级自启动同样应保持关闭(与主数据库一致),由集群统一管理。


4. 接管验证

4.1 接管就绪状态检查

激活完成后,集群接管的正常状态如下:

# 集群状态(root):两节点 online;msl 在 hana01 为 Master、hana02 为 Slave
crm status

# 资源代理内部状态(root):优先使用 SAPHanaSR-showAttr 查询
SAPHanaSR-showAttr
# SAPHanaSR-showAttr 输出示例(经典版)
Host \ Attr clone_state remoteHost roles           ... site    srmode sync_state ...
------------------------------------------------------------------------------------
hana01      PROMOTED    hana02     4:P:master1:...     SiteA   sync   PRIM       ...
hana02      DEMOTED     hana01     4:S:master1:...     SiteB   sync   SOK        ...
说明
  • 请使用 SAPHanaSR-showAttr 查询资源代理内部值——不要用 crm_attribute 等集群命令直接读取(属性的存储位置与参数名可能随版本变化,showAttr 会从正确位置取值);SAPHanaSR-showAttr 是测试工具,不适用于自动化系统监控;--format=script 与 SAPHanaSR-filter 的过滤查询需要 SAPHanaSR 0.153 及以上版本。

  • 输出中的 roles 以 4: 开头表示节点上的实例处于运行状态(4:P 主库 / 4:S 备库),sync_state 为 SOK 表示复制同步;具体列名可能随版本调整,请以 roles 前缀作为关键判读依据。

  • 官方测试前提(SUSE 官方经典版指南):两节点已启动、为集群成员,HANA RDBMS 运行,系统复制同步(SOK),集群无遗留迁移约束与失败动作(空闲状态)。

4.2 故障接管测试:停止主库(官方用例 STOP_PRIMARY_SITE_A)

在业务窗口外执行(会停止主库服务)。步骤如下:

步骤 1:停止主库(hana01)

# 在 hana01 以 <sid>adm 执行
HDB stop

步骤 2:观察集群自动接管,预期结果(按官方经典版指南测试用例的预期):

  • 集群检测到已停止的主库(hana01)并将该资源标记为失败;

  • 集群提升备库(hana02)为新主库;

  • VIP 自动迁移到新主库(hana02);

  • 一段时间后,停止的原主库(hana01)的 sync_state 显示为 SFAIL;

  • 由于 AUTOMATED_REGISTER=false,集群不会自动重启原主库实例,也不会自动注册到新主库;

  • 完成恢复流程后,集群的失败动作被清理,复制对恢复为同步(SOK)。

步骤 3:恢复——将原主库注册为新备库并交回集群管理

# 在 hana01 以 <sid>adm 执行(站点名沿用 SiteA)
hdbnsutil -sr_register --remoteHost=hana02 --remoteInstance=<INO> \
    --replicationMode=sync --operationMode=logreplay \
    --name=SiteA
# 在任一节点以 root 执行:让集群重新监测并启动该资源
crm resource refresh rsc_SAPHana_<SID>_HDB<INO> hana01

等待复制恢复同步后验证:

# 在 hana02(新主库)以 <sid>adm 执行
HDBSettings.sh systemReplicationStatus.py --sapcontrol=1
# overall_replication_status=ACTIVE

# root
SAPHanaSR-showAttr
# 输出中 hana02 的 roles 以 4:P 开头(新主库)、hana01 的 roles 以 4:S 开头(新备库)
说明
  • 本测试会互换主备角色(测试后 hana02 为主库)。如需将角色恢复为初始状态(hana01 主库),按 4.3 节受控切换流程执行。

  • 若已将 AUTOMATED_REGISTER 改为 true,恢复步骤(手动注册 + refresh)由集群自动完成,可跳过(见第 5 章)。

  • Cost Optimized 场景(PREFER_SITE_TAKEOVER=false)的预期结果不同:集群会优先在原节点重启主库(本例中重启会成功,不发生接管);只有本地重启失败或整节点故障时才触发接管路径。验证接管需模拟节点级故障,或参考上述预期结果调整测试方法。

  • SUSE 官方经典版指南给出的测试用例集更全(半自动与全自动两组),包括:停止站点 B 的主库、崩溃主库(HDB kill-9,站点 A/B 各一例)、崩溃主库节点、停止/崩溃备库、崩溃备库节点、primary indexserver 崩溃、复制网络故障等,恢复流程同理。上线前应结合业务需求补充测试用例(如节点掉电、网络隔离)并全部通过。

4.3 受控切换(计划内主备互换)

计划内维护(如硬件升级)时,用以下两种方式之一互换主备角色(假设当前 hana01 为主库、hana02 为备库,目标为互换)。注意:系统复制处于失去同步状态(SFAIL)时不应执行切换。

方式一:SAP 工具集(手工接管,全程受控)

# 1) 将多状态资源置入维护模式(任一节点 root)
crm resource maintenance msl_SAPHana_<SID>_HDB<INO>

# 2) 停止主库(hana01,<sid>adm);确认主库已完全停止后再继续
HDB stop

# 3) 在备库执行接管(hana02,<sid>adm)
hdbnsutil -sr_takeover

# 4) 将原主库注册为新备库(hana01,<sid>adm)
hdbnsutil -sr_register --remoteHost=hana02 --remoteInstance=<INO> \
    --replicationMode=sync --operationMode=logreplay \
    --name=SiteA

# 5) 启动新备库(hana01,<sid>adm)
HDB start

等待 SAPHanaSR-showAttr 中两个实例均恢复在线(roles 以 4 开头;新备库角色为 S)之后:

# 6) 让集群重新监测(任一节点 root)
crm resource refresh msl_SAPHana_<SID>_HDB<INO>

# 7) 退出维护模式(任一节点 root)
crm resource maintenance msl_SAPHana_<SID>_HDB<INO> off
说明

多状态资源置入维护模式后,preTakeover() Hook(susTkOver)将放行手动接管请求;集群正常运行期间,手动接管会被阻止——这正是 susTkOver 的作用。

方式二:集群工具集(半自动,仅 force 受支持)

# 1) 创建 “move away + force” 规则:集群先停止当前主库,再将备库提升为主库(任一节点 root)
crm resource move msl_SAPHana_<SID>_HDB<INO> force
重要

迁移必须使用 force 选项:不带 force 的迁移会在未停止原主库的情况下引发接管(双主风险),不受支持。系统复制未同步(SFAIL)时不应执行迁移。

等待新主库提升完成后再继续:

# root:确认新主库 roles 以 4:P 开头
SAPHanaSR-showAttr --format=script | \
   SAPHanaSR-filter --search='roles'
# 2) 将原主库注册为新备库(原主库节点,<sid>adm;站点名沿用原站点名)
#    若已启用 AUTOMATED_REGISTER=true,注册由集群自动完成,可跳过本步骤
hdbnsutil -sr_register --remoteHost=hana02 --remoteInstance=<INO> \
    --replicationMode=sync --operationMode=logreplay \
    --name=SiteA

# 3) 清除 move 规则,允许集群启动新备库(任一节点 root)
crm resource clear msl_SAPHana_<SID>_HDB<INO>

最后确认新备库启动并同步(roles 以 4:S 开头),复制状态回到 ACTIVE。

说明

crm resource 的 move/clear 命令此前分别命名为 migrate/unmigrate;旧名仍然有效但已属过时(obsolete)用法,请使用新名。


5. 关键参数说明

5.1 资源代理参数

SAPHana 资源的关键参数与官方推荐值:

参数

Performance Optimized

Cost Optimized

说明

PREFER_SITE_TAKEOVER

true

false

是否优先切换到备站(而非在原节点重启故障主库)。Cost Optimized 场景建议 false:备库配置了内存限制且表预加载关闭(《SAP HANA HSR 配置》1.4 节),接管代价高,优先本地重启

AUTOMATED_REGISTER

false / true

false / true

是否自动将原主库注册为新主库的备库。设为 false 时原主库必须人工注册,集群不会启动未注册实例——避免双主。初始配置 false,上线验证通过后可按需改为 true

DUPLICATE_PRIMARY_TIMEOUT

7200

7200

双主场景下两个主库时间戳所需的差值(秒)。差值不足时集群将其中一个或两个实例保持 WAITING 状态,给管理员处置时间;若原主节点整体崩溃,超过该时间后原主库将被自动注册(数据由系统复制覆盖);若仅 RDBMS 崩溃则立即注册

补充说明:

  • 验证通过后再启用自动化:建议保持 AUTOMATED_REGISTER=false 完成第 4 章全部测试,确认接管行为符合预期后,再执行 crm resource param rsc_SAPHana_<SID>_HDB<INO> set AUTOMATED_REGISTER true。启用后,接管测试的恢复步骤由集群自动完成。

  • 操作超时:start=3600、stop=600、promote=900、monitor(Master 间隔 60s / Slave 间隔 61s,超时 700s)为官方经典版模板值;demote 操作官方模板未显式列出(RA 建议最小超时 320s,angi 模板显式定义)。HANA 的启动/停止/提升操作耗时较长,不建议随意调小;如需调优请对照 manpage ocf_suse_SAPHana(7)。

  • 默认值与粘性:resource-stickiness=1000 防止资源在节点间非必要漂移;migration-threshold=5000、op_defaults timeout=600 与 record-pending=true 均为官方模板值,直接沿用。

  • 维护状态机制:SAPHana 多状态资源加载时带 maintenance=true,只有执行 3.5 节的激活序列后才开始接管实例;后续维护操作(如端口/实例级调整)也应先将多状态资源置入维护模式,操作序列示例见 manpage SAPHanaSR_maintenance_examples(7)。

  • priority 与隔离竞速:SAPHana 设 meta priority=100,方案 B 下配合 priority-fencing-delay=60,让承载主库的节点在隔离竞速中占先(机制见《集群初始化》2.2 节)。

  • 与 angi 的参数差异:ON_FAIL_ACTION 为 angi(SAPHanaController)独有参数;经典版通过 susChkSrv Hook 的 action_on_lost 参数实现相应的加速接管行为(本文 2.2 节设为 stop)。

  • 复制模式限制:受控复制仅支持 sync 与 syncmem,不支持 async(官方要求,见《SAP HANA HSR 配置》1.3 节)。

5.2 Cost Optimized 补充说明

  • 接管时的行为:susCostOpt.py 的 postTakeover() 在新主库上执行 SQL,解除 global.ini 中 [memorymanager] global_allocation_limit 限制并恢复 [system_replication] preload_column_tables(同时修改内存与持久化配置)。接管并发 SQL 的过程会延长接管时间。

  • 回退到原始状态的恢复流程(概要,完整命令示例见 manpage susCostOpt.py(7)):

  1. 将 HANA 多状态资源置入维护模式;

  2. 清理 HANA primitive 资源;

  3. 原主库站点:将原主库注册为新备库;

  4. 原主库站点:启动新备库,等待 SR 同步完成;

  5. 现主库站点:停止主库;

  6. 原主库站点:在备库上执行 hdbnsutil -sr_takeover;

  7. 现主库站点(已停止的原主库):修改 global.ini,恢复备库的内存限制与预加载设置;

  8. 现主库站点:将原主库注册为新备库;

  9. 现主库站点:启动新备库,等待 SR 同步完成;

  10. 刷新 HANA 多状态资源(crm resource refresh);

  11. 将 HANA 多状态资源退出维护模式。

说明
  • 第 7 步也可以在现主库停止之前预先对该节点完成(即提前按“备库参数”准备好 global.ini);

  • 若已启用 AUTOMATED_REGISTER=true,注册相关步骤可由集群自动完成;

  • 操作前后都应检查 Linux 集群与 HANA 系统复制的状态,站点名必须与集群已知的名称一致。


至此,SAPHanaSR 经典版的集群接管与资源配置完成:HANA 主备实例由 Pacemaker 集群接管,具备故障自动接管与受控切换能力。日常维护操作(计划内停机、维护模式进入/退出、接管后的角色回退等)请参考 manpage SAPHanaSR_maintenance_examples(7);可选的只读访问(Read-Enabled)配置思路见《集群接管与资源配置(SAPHanaSR-angi)》第 6 章,经典版将其中 colocation 的角色由 Unpromoted 相应改为 Slave。如《选型与决策指引》选定的是 SAPHanaSR-angi,请转《集群接管与资源配置(SAPHanaSR-angi)》。