本章列举了一些常见的数据守护场景及其处理方法,并相应地介绍监视器命令的执行流程。
6.1 正常运行状态
守护系统正常运行时,同一个守护进程组中,只有一个主库,其他的都是备库。
主库处于 Open 状态,主库守护进程也处于 Open 状态,本地没有守护进程控制文件,其内存值是 Valid 有效状态。
所有备库也处于 Open 状态,所有备库守护进程处于 Open 状态,本地没有守护进程控制文件,其内存值是 Valid 有效状态。
主库到所有备库的归档也都处于 Valid 有效状态。
MPP 主备系统中,所有主库的 dmmpp.ctl 都处于一致状态。
6.2 数据守护的启动
Normal 模式的库默认以 Open 状态启动,也可以通过增加启动参数 Mount 将数据库启动到 Mount 状态。而 Primary/Standby 模式的库启动后,自动进入 Mount 状态,因此,数据守护系统启动时,所有数据库实例处于 Mount 状态。所有守护进程处于 Startup 状态。如果实例还未启动到 Mount 状态(比如还处于 After redo 状态),守护进程不会通知实例 Open。
Local 守护类型的守护进程,直接 Open 数据库实例,并修改守护进程状态为 Open。Global 守护类型的守护进程,需要相互协调信息,自动将数据库实例切换到 Open 状态,并将守护进程状态也切换为 Open 状态。
Global 守护类型的守护进程通知本地库 Open 的总体原则:
- 对于备库,如果可加入远程任意一个库,则允许将其 Open;
- 对于主库,如果远程所有库都可加入自己,则允许将其 Open。
还有一些细节条件这里不再具体列出,如果通过监视器没有观察到主库或备库 Open,可以借助监视器的 Check Open 命令查找原因,根据命令返回的原因考虑是否进行人工干预,比如需要通过监视器命令强制 Open 主库或备库。
注意手动方式启动数据守护系统时,对于守护进程,数据库实例和监视器的启动顺序没有严格要求,也可以通过监视器命令启动守护系统(前提是所有守护进程已经启动)。
启动流程中,守护进程在通知主库Open之前,会先收集出和主库数据一致的备库(备库的ALSN信息和主库的FLSN信息相等),守护进程会将这些备库的归档设置为Valid有效状态,其他数据不一致的备库则设置为Invalid无效状态。Primary模式数据库实例切换为Open状态时,需要回滚活动事务、Purge已提交事务,并重构回滚段,会引发数据变化、LSN增长。对归档无效的备库,在数据守护启动完成后,主备库数据肯定是处于不一致状态。
主库守护进程Open主库后,会修改INST_RECOVER_TIME内存值为3秒(默认60秒),确保归档状态无效的备库Open后,尽快启动故障恢复流程,同步主库数据完成后,重新将归档设置为Valid状态。
如果在故障恢复流程完成之前,主库故障,并且不存在归档状态有效的备库,则无法执行备库接管;备库强制接管会引发守护进程组分裂。
读写分离集群,在Timely或Realtime归档变为Valid之前,不会在备库上创建数据库连接,只读操作也无法分流到对应的备库。
6.3 强制 Open 数据库
正常情况下,守护进程 dmwatcher 可以自动 Open 数据库实例,但某些情况下(比如备库硬件故障无法启动),数据守护系统不满足 6.2 数据守护的启动介绍的启动条件,我们可以通过监视器执行 Open database 命令强制 Open 数据库实例。主备库都可以强制 Open,其执行流程如下:
假设需要强制 Open 数据库 A,只需要启动一个监视器,登录后输入 Open database A 即可完成强制启动。
如果数据库 A 是 Standby 模式,强制 Open 的执行流程如下:
- 通知 A 的守护进程切换为 Open Force 状态
- 通知 A 执行 Open 操作
- 通知守护进程切换 Open 状态
如果数据库 A 是 Primary 模式,强制 Open 的执行流程如下:
- 通知 A 的守护进程切换为 Open Force 状态
- 修改 A 到所有归档目标的实时归档/即时归档状态为无效
- 通知 A 执行 Open 操作
- 通知守护进程切换 Open 状态
Primary 模式数据库实例切换为 Open 状态时,需要回滚活动事务、Purge 已提交事务,并重构回滚段,会引发数据变化、LSN 增长。因此,这个操作可能会引发守护进程组分裂,比如下面的场景:
- 主库 A 故障
- 备库 B 接管,成为主库
- B 故障
- A 重启,并强制 Open
- A 和 B 数据不一致,并且无法恢复到一致状态。此时,B 重启,就会产生守护进程组分裂。
注意强制Open主库前,会设置主库到所有归档目标的实时归档/即时归档为Invalid状态。
强制 Open 主库命令,会修改主库守护进程 INST_RECOVER_TIME 内存值为 3 秒(默认 60 秒),确保主库 Open 后,尽快启动故障恢复流程,同步主库数据完成后,重新将归档设置为 Valid 状态。
如果在故障恢复流程完成之前,主库故障,将无法执行备库接管;备库强制接管会引发守护进程组分裂。
6.4 关闭数据守护系统
关闭守护系统时,必须按照一定的顺序来关闭守护进程和数据库实例。特别是自动切换模式,如果退出守护进程或主备库的顺序不正确,可能会引起主备切换,甚至造成守护进程组分裂。
通过监视器执行 Stop Group 命令关闭数据守护系统,是最简单、安全的方式。命令执行成功后,数据库实例正常关闭。但守护进程并没有真正退出,而是将状态切换为 Shutdown 状态。
Stop Group 命令内部流程如下:
- 通知守护进程切换为 Shutdown 状态
- 通知主库退出
- 通知其他备库退出
如果使用手动方式关闭数据守护系统,请严格按照以下顺序执行:
- 如果启动了确认监视器,先关闭确认监视器(防止自动接管)
- 关闭备库守护进程(防止重启实例)
- 关闭主库守护进程(防止重启实例)
- Shutdown 主库
- Shutdown 备库
如果是只关闭主库,并且不想引发备库自动接管,有以下两种方法:
方法一:
1.通过 Detach database 命令将所有备库分离
2.通过 Stop database 命令退出主库
方法二:严格按照以下顺序执行:
- 通过 Stop dmwatcher 命令关闭所有守护进程监控
- 手动正常退出主库
如果是只关闭备库,并且不想引发主库发送日志失败进入 Suspend 状态,请严格按照以下顺序执行:
- 通过 Detach database 命令将备库分离出数据守护系统
- 正常退出备库(手动退出或者通过 Stop database 命令退出)
注意关闭整个数据守护系统时,先关闭主库再关闭备库,顺序一定不能错。对于本地守护类型的库,在关闭数据守护系统时,不受此顺序限制。
因为主库 Shutdown 过程中,需要 Purge 所有已提交事务,会修改数据,并产生 Redo 日志。如果先 Shutdown 备库,会导致主库发送归档日志失败,并且由于主库已经处于 Shutdown 状态,会导致主库异常关闭。
- 关闭后升级数据守护系统
当正常关闭数据守护系统后,可以将守护系统主备库都升级到新版本然后正常启动数据守护系统以达到升级整个数据守护系统版本的目的。如果需要不中断数据库服务升级数据守护系统,可使用滚动升级功能。
升级版本后重新启动数据守护系统时,由于升级过程中可能涉及系统表、动态视图等的修改,需要在主库版本升级后将升级过程中的 Redo 日志发送到备库,备库通过重做这段 Redo 日志进行版本升级。在此过程中,不允许对备库进行访问,否则会报“备库版本升级时不允许访问”的错误。Redo 日志重做完成后,备库允许正常访问。
6.5 主备库切换
主库维护,滚动升级等场景,可以执行 Switchover 命令,实现主备库切换。如果存在多个备库,需要先执行 Choose
Switchover 命令,选出守护进程组中可以切换的备库。
Choose Switchover 命令选择可切换备库的条件如下:
- 主库守护进程是 Open 状态
- 备库守护进程是 Open 状态
- 主、备库的 OPEN 记录项内容相同,并且守护进程控制文件是 Valid 有效状态(内存值)
- 主库正常运行
- 备库正常运行
- 主库处于 Open 状态
- 备库处于 Open 状态
- 主库到备库的归档是 Valid 状态
假定选出的可切换备库是 B,Switchover 切换流程如下:
- 通知主备库守护进程,切换为 Switchover 状态
- 通知主库(A) Mount
- 实时或 MPP 主备环境下,通知备库(B) APPLY KEEP_RLOG_PKG
- 通知备库(B) Mount
- 通知(A) 切换为 Standby 模式
- MPP 主备环境下,通知(A)修改 MPP_INI 内存值为 0
- 通知(B) 切换为 Primary 模式
- 通知(B) 修改所有归档目标的归档状态为无效
- MPP 主备需要通知各组活动主库更新 dmmpp.ctl 文件,参考后文说明
- 通知新的备库(A) Open
- 通知新的主库(B) Open
- 通知主备库守护进程切换为 Open 状态
- 清理所有守护进程上记录的监视器命令执行信息
其 cmmpp.ctl 步骤说明如下:
- 收集各组的活动主库信息,构造新的 dmmpp.ctl 文件。
主库收集条件:
1)组中只有一个活动主库,不存在多个 OPEN 主库
2)主库守护进程不是 Error 状态,且控制文件是有效状态
3)主库实例不是 Error 状态
- 通知步骤 1 中收集到的主库更新 dmmpp.ctl 文件
首先通知执行 Switchover 命令的守护进程组的主库执行更新操作,再通知其他组的主库执行更新操作。通知其他组执行更新操作时,会先将其主库的守护进程切换为 Mppctl update 状态,更新完成后,再切换回 Open 状态。
对步骤 1 中不符合收集条件的组,在步骤 2 中跳过不再处理,后续待其主库恢复正常后,可借助 recover mppctl 命令恢复 dmmpp.ctl 文件到一致状态。
更新 MPP 控制文件时,服务器自动断开当前所有的会话连接,回滚未提交事务,挂起所有工作线程,该过程可能会持续一段时间。
- 根据步骤 2 的结果决定是否继续执行 Switchover 的后续步骤
步骤 2 中如果某个活动主库更新失败,则终止切换,执行失败。
注意主备库切换在实现逻辑上等同于主备库正常状态下用户主动发起的Takeover 操作。Swithover完成后,主备库之间数据是不完全同步的,要由新主库B的守护进程通过Recovery流程,重新同步数据到新备库A。
Switchover命令会修改切换后主库守护进程INST_RECOVER_TIME内存值为3秒(默认60秒),确保尽快启动故障恢复流程,同步主库数据完成后,重新将归档设置为Valid状态。在故障恢复流程完成之前,再次执行Switchover命令会报错,如果主库故障,备库接管将会报错;备库强制接管会引发守护进程组分裂。
主库在切换时会先被设置为Mount状态和Standby模式,此时若主库上的已有连接执行操作,可能会触发-510(系统处于MOUNT状态)或-710(试图在STANDBY模式下,修改用户库)报错。
6.6 主库故障、备库接管
当出现硬件故障(掉电、存储损坏等)原因导致主库无法启动,或者是主库内部网卡故障导致主库短期不能恢复正常的情况下,可使用备库接管功能,将备库切换为主库继续对外服务。
故障自动切换模式下,确认监视器会自动选择符合条件的备库进行接管。
故障手动切换模式下,可以先在监视器上执行 Choose Takeover 命令,选出守护进程组中可以接管的备库。
为了避免备库接管后,造成守护进程组分裂,手动执行 Takeover 必须满足下列条件:
- 主库是 Primary 模式、Open 状态时,发生故障
- 手动 Takeover 允许主库守护进程故障,但是要求故障前是 Open/Recovery 状态;或者主库守护进程没有故障(非 ERROR 状态)
- 主库故障前到接管备库的归档状态为 Valid
- 接管备库是 Standby 模式、Open 状态
- 接管备库的守护进程控制文件状态为 Valid(内存值)
- 故障主库和接管备库的 Open 记录项内容相同
假设主库 A 故障时,在故障自动切换模式下确认监视器自动选出待接管备库 B 并通知备库 B 自动接管,或者在故障手动切换模式下,通过监视器上的 Choose
Takeover 命令,选出待接管备库 B,在监视器上输入 Takeover 命令通知备库 B 执行接管,这两种方式的接管执行流程是一样的。
以备库 B 为例,接管的执行流程包括:
- 监视器通知守护进程(B)切换为 Takeover 状态
- 实时主备或 MPP 主备环境下,通知备库(B) APPLY KEEP_RLOG_PKG
- 通知备库(B) Mount
- 通知(B) 切换为 Primary 模式
- 通知(B) 修改到所有归档目标的归档状态为 Invalid
- MPP 主备需要通知活动主库更新 dmmpp.ctl 文件(步骤参考 6.5 主备库切换)
- 通知新的主库(B) Open
- 通知守护进程(B)切换为 Open 状态
注意例如,主库C故障,备库B接管。执行Takeover命令后,会修改守护进程(B)的INST_RECOVER_TIME内存值为3秒(默认60秒),确保尽快启动B->C的故障恢复流程,同步主库数据完成后,重新将B->C的归档设置为Valid状态。在故障恢复流程完成之前,主库(B)故障,备库(C)无法接管;强制备库(C)接管会引发守护进程组分裂。
6.7 备库强制接管
在备库接管失败后,主库仍然不能启动或者及时恢复对外服务的情况下,用户可以使用 Takeover Force 命令,进行备库强制接管。强制接管具有一定的风险,可能因为备库和故障主库数据不一致,而造成部分数据的丢失,出现数据库分裂的情况,所以应该慎重使用。
与正常 takeover 命令相比,强制接管时系统不会对故障主库与待接管备库的数据一致性进行检查,而是将这一点交给用户预判。若接管前主备库的数据是一致的,则强制接管与正常 takeover 效果相同,接管成功后不会出现数据丢失的情况,故障主库重启后也能正常加回集群。若接管前主备库的数据不一致,则强制接管后会存在数据丢失,故障主库重启后无法加回集群,出现集群分裂。
在主备库之间的数据不一致的情况下,如果用户认为丢失小部分数据的影响可以忽略,或者该影响小于主库持续宕机造成的影响,则可以考虑进行 takeover force 强制接管。
下面列举了几种典型的主备库数据不一致的场景,在这些场景下执行强制接管后,可能会出现数据丢失。场景一,主库故障前到备库的归档状态为 INVALID,此时主库和备库之间已经存在日志差。该备库强制接管后会出现数据丢失。场景二,主库故障前到备库的归档状态为 VALID,但该备库处于 Timely 即时归档模式下。若主库在将日志写入本地联机日志文件之后立即发生故障,尚未将该日志发送给备库。则备库强制接管后会丢失这条日志的内容。
典型的主备库数据一致的场景:REALTIME 归档模式,主库故障前到备库的归档状态为 VALID。由于 REALTIME 归档流程为主库先发送日志到备库,等待收到所有备库的响应消息后再将该日志写入本地的联机日志文件中,所以在主库故障后其联机日志文件中已经写入的日志一定不会备库收到的日志更多。这种场景下执行强制接管后不会出现数据丢失,故障主库重启后也能够作为备库重新加入集群,不会发生集群分裂。
强制接管,先通过 Choose Takeover Force 选出符合强制接管条件的备库,再执行 Takeover Force 命令。备库强制接管时,如果接管备库是处于 Mount 状态/Standby 模式的库,则会自动 Open 备库,其他执行流程与备库接管一致。强制接管的条件包括:
- 不存在活动主库
- 备库守护进程处于 Open 或 Startup 状态
- 备库实例运行正常
- 备库是 Standby 模式
- 备库处于 Open 或 Mount 状态
- 备库的 KLSN 必须是所有备库中最大的
- 备库守护进程控制文件必须有效
注意与Takeover命令一样,Takeover Force命令会修改主库守护进程的INST_RECOVER_TIME内存值为3秒(默认60秒),确保尽快启动故障恢复流程。
强制接管具有一定的风险,可能导致备库和故障主库数据不一致,从而造成部分数据的丢失、数据库分裂,所以应该综合考虑当时情况,慎重使用。 对于强制接管并且引发分裂的场景,故障主库重启恢复后,只有当新接管的主库处于 Primary & Open,并且实例是活动情况下,才会主动设置原来的主库为 Split 分裂状态。如果新接管主库也被重启到 Mount 状态,由于两个主库互相不可加入,守护进程无法在两个 Mount 主库之间选出有效主库,需要用户干预。
6.8 主库故障重启(备库接管前重启)
主库故障后立即重启,此时主库的守护进程变成 Startup 状态,重新进入守护进程的启动流程,将数据一致的备库归档设置为有效状态,其余备库归档设置成无效状态,并重新 Open 主库。Open 成功后继续作为主库,当检测到归档状态无效的备库正常时会启动 Recovery 处理流程,重新同步主备库数据。
6.9 备库故障处理
备库产生故障(硬件故障或者内部网卡故障)时,主库的处理流程对手动切换、自动切换模式处理上有些差异。
- 手动切换模式
对于手动切换模式,检测到备库故障,满足 Failover 条件时,主库的守护进程立即切换到 Failover 状态,执行对应的故障处理,如果不满足切换 Failover 条件,则保持当前状态不变。
手动切换模式下,主库守护进程切换 Failover 条件:
- 备库实例故障,或者主备库之间出现网络故障,或者备库重演时校验 LSN 不匹配,这三种场景下引发主库同步日志到备库失败挂起,主库实例处于 Suspend 状态
- 主库到此备库的归档状态是 Valid(读写分离集群没有此限制)
- 主库的守护进程处于 Startup、Open 或 Recovery 状态
- 当前没有监视器命令正在执行
- 自动切换模式
对于自动切换模式,主库的守护进程会自动判断切换到 Failover 状态或者 Confirm 确认状态,如果两种状态切换条件都不满足,则保持当前状态不变。
自动切换模式下,主库守护进程不进入 Confirm 确认状态,直接切换到 Failover 条件:
- 前四项条件,和上面列出的手动切换条件相同
- 备库实例故障,备库守护进程正常
如果只满足条件 1,不满足条件 2,则主库守护进程会先进入 Confirm 确认状态,等待确认监视器的确认消息。主库的守护进程进入 Confirm 确认状态后,会有下面几种不同的处理:
- 主库和确认监视器之间网络连接正常
主库的守护进程收到了确认监视器返回的确认消息,如果确认监视器认定可以执行 Failover,则主库的守护进程会切换为 Failover 状态并执行对应的处理;如果确认监视器认定不满足执行 Failover 条件,则主库的守护进程会一直保持在 Confirm 状态。确认监视器认定主库可以执行 Failover 条件:
- 主库守护进程处于 Confirm 状态
- 主库实例正常,处于 Suspend 状态
- 主库没有被接管,不存在其他主库
- 没有 takeover/switchover 命令在执行
- 当前所有归档有效的备库均可以加入主库
- 主库和确认监视器之间网络连接异常,或者没有启动确认监视器。满足下面条件后主库允许切换至 Failover 状态执行故障处理:
- 主库实例正常,处于 Suspend 状态
- 备库守护进程正常
- 主库没有被接管,不存在其他主库
- 没有 takeover/switchover 命令正在执行
- 备库故障前可以加入主库
- 主库和确认监视器网络恢复正常后,主库已经被接管。老主库的守护进程切换为 Startup 状态,重新判断是否可加入新主库。
主库守护进程进入 Failover 状态后的执行流程(自动或手动切换模式下执行流程相同):
- 对实时主备或 MPP 主备,通知主库修改发送归档失败的备库归档状态无效
- 通知主库重新 Open。
- 将主库的守护进程切换为 Open 状态
6.10 公共网络故障
主库公共网络故障,主备库正常、内部网络正常情况下,用户无法连接主库执行正常的数据库操作。这种情况下,用户可以通过 Switchover 命令,将备库切换为主库,确保数据库服务不受影响。
读写分离集群中备库公共网络故障,主备库正常、内部网络正常情况下,用户的所有请求会自动分发到主库执行。
6.11 内部网络故障
DM 数据守护对内部网络的可靠性提出了很高的要求,但是在实际应用中(比如异地容灾),存在很多不可控因素,内部网络无法保证绝对可靠。守护进程和守护进程之间、守护进程和监视器之间通过超时机制来检测是否出现故障,当内部网络出现故障时,超过设置时间未收到远程消息,会认定远程故障。
下面的表格说明在外部网络正常时,内部网络故障的场景以及守护进程的处理策略:
故障类型 | 手动切换处理策略 | 自动切换处理策略 |
---|---|---|
主库内部网卡故障 | 归档失败时,主库挂起,主库 Failover,归档设置无效,异步工作 | 归档失败时,主库挂起,主库守护进程保持 Confirm 状态,确认监视器自动寻找备库自动接管。详见 4.3 状态确认、4.4 自动接管、6.6 主库故障、备库接管。 因为外网还是正常的,在经过 SESS_FREE_IN_SUSPEND 参数配置的时间后,老主库会自动断开所有连接,以便应用连接能够转移到新接管的主库上,详见下文说明。 注:此场景下主备库之间无法通信,但确认监视器仍然可以和备库的守护进程正常通信 |
备库内部网卡故障 | 归档失败时,主库挂起,主库 Failover,归档设置无效,异步工作 | 归档失败时,主库挂起,主库守护进程 Failover(经过 Confirm 状态确认后 Failover),归档设置无效,异步工作。详见 4.3 状态确认、4.4 自动接管、6.9 备库故障处理。 注:此场景下主备库之间无法通信,但确认监视器仍然可以和主库的守护进程正常通信 |
主备库交换机故障 | 归档失败时,主库挂起,主库 Failover,归档设置无效,异步工作 | 归档失败时,主库挂起,主库守护进程保持 Confirm 状态,备库不会自动接管。 注:此场景下主备库之间,以及和确认监视器之间都无法正常通信 |
主备网卡同时故障 | 归档失败时,主库挂起,主库 Failover,归档设置无效,异步工作 | 归档失败时,主库挂起,主库守护进程保持 Confirm 状态,备库不会自动接管。 注:此场景下主备库之间,以及和确认监视器之间都无法正常通信 |
自动切换模式下,当发生主库内部网络故障而其他网络均正常时,归档失败,主库 Suspend,会导致连接主库的会话被挂起,一直无法返回,备库自动接管后,这些会话连接无法自动切换到新主库上。为此,DM 采用超时机制断开由于归档失败导致挂起时的所有会话,通过配置 dm.ini 中的 SESS_FREE_IN_SUSPEND 实现,默认 60s。
网络故障恢复后,对于手动切换模式,没有强制接管的情况下,主库的守护进程会自动判断备库是否能加入,能加入则启动 Recovery 流程。对于自动切换模式已经被接管的情况,守护进程会将被接管的老主库强制退出(Shutdown),老主库重启后,还需要守护进程再去判断是否可作为备库重加入守护系统,如果可以,则启动恢复流程(切换为 Standy 模式,重新将实例 Open),如果不能,才修改为分裂状态。
当内部网络是由于拔掉网线、或者禁用网卡等原因导致的故障,MAL 系统检测到链路断开的时间由 dmmal.ini 中配置的 MAL_CHECK_INTERVAL 以及 MAL_CONN_FAIL_INTERVAL 决定。会话的中断时间会比杀掉实例、掉电等花费的时间长。下面举例说明:
dmmal.ini 配置
MAL_CHECK_INTERVAL = 10
MAL_CONN_FAIL_INTERVAL = 10
dmwatcher.ini 配置
DW_ERROR_TIME = 10
拔掉备库网线后,主库上 MAL 检测线程根据 MAL_CHECK_INTERVAL 间隔检查,时间<=10s,检查认定网络故障需要 10s,再加上守护进程认定远程网络故障时间 DW_ERROR_TIME 为 10s,在最坏的情况下,应用连接等待主库响应最长的时间可能会是三个时间的累加,也许会达到 30s。
6.12 备库异常处理
备库实例正常,只是内部网络出现异常,比如网络不稳定、网速急速下降,或者备库自身的软硬件出现问题,比如操作系统原因或磁盘读写速度异常降低等情况下,备库响应主库的时间变慢,这种情况下,主库守护进程会自动进行检测处理。
6.13 故障库数据同步
当实例由于各种原因故障,重启或者网络恢复后,守护进程会自动判断能否加入当前主库系统。恢复的中间过程可通过附录中的动态视图进行查看。
6.14 备库重建
当主备库所在硬件出现故障、或者数据库文件损坏导致数据损毁时,可按照第 7 章数据守护搭建中介绍的几种方式来重新准备数据。
重建库要选定一个当前有效库或者一个历史备份。下面以单节点备库 B 数据损坏,重新配置数据为例,说明备库重建流程:
- 重新初始化数据库
./dminit path=/dm/data SYSDBA_PWD=DMdba_123 SYSAUDITOR_PWD=DMauditor_123
- 启动 DIsql 登录主库 A,执行联机备份
SQL> BACKUP DATABASE FULL BACKUPSET '/dm/data/BACKUP_FILE_01';
注意,如果主库 dm.ini 中的 USE_AP 设置为 1,则需要先启动 dmap 服务。
- 将备份文件拷贝至 B 所在的机器上,执行脱机还原与恢复
./dmrman CTLSTMT="RESTORE DATABASE '/dm/data/DAMENG/dm.ini' FROM BACKUPSET '/dm/data/BACKUP_FILE_01'"
./dmrman CTLSTMT="RECOVER DATABASE '/dm/data/DAMENG/dm.ini' FOR STANDBY FROM BACKUPSET '/dm/data/BACKUP_FILE_01'"
./dmrman CTLSTMT="RECOVER DATABASE '/dm/data/DAMENG/dm.ini' UPDATE DB_MAGIC"
- 重新配置 B 的 dm.ini、dmmal.ini、dmarch.ini 和 dmwatcher.ini 配置文件
- 以 Mount 方式启动 B
./dmserver /dm/data/DAMENG/dm.ini mount
- DIsql 登录 B,设置 OGUID,修改备库模式
SQL>SP_SET_PARA_VALUE(1, 'ALTER_MODE_STATUS', 1);
SQL>sp_set_oguid(82379);
SQL>alter database standby;
SQL>SP_SET_PARA_VALUE(1, 'ALTER_MODE_STATUS', 0);
上述语句中,sp_set_oguid()设置的 OGUID 值必须与主库一致。若重建的备库仍和主库在同一个集群中,则还原后备库的 OGUID 值与主库是一致的,sp_set_oguid()步骤可省略。
- 启动 B 的守护进程
./dmwatcher /dm/data/DAMENG/dmwatcher.ini
执行以上步骤后,恢复 B 的准备过程已经完成。接下来,数据守护系统会将 B 作为备库重加入数据守护系统,A 的守护进程会自动通知同步数据到 B,最终恢复主备库数据到一致状态。
如果数据规模比较大、联机备份耗时较长、应用压力比较大的情况下,主库联机备份、备库脱机还原过程中,主库可能又新产生了大量归档日志。使用上述步骤重建备库后,主库向备库同步历史数据的时间会比较久,主备库数据会在比较长的一段时间内处于不一致状态。对这种情况,用户可以通过归档备份、还原和归档恢复功能,将备库数据恢复到更加接近主库的最新状态,有效减少备库加入主备系统后的历史数据同步时间。执行步骤如下:
- 重新初始化数据库
./dminit path=/dm/data SYSDBA_PWD=DMdba_123 SYSAUDITOR_PWD=DMauditor_123
- 启动 DIsql 登录主库 A,执行联机备份
SQL> BACKUP DATABASE FULL BACKUPSET '/dm/data/BACKUP_FILE_02' WITHOUT LOG;
注意,如果主库 dm.ini 中的 USE_AP 设置为 1,则需要先启动 dmap 服务。
- 将备份文件拷贝至 B 所在的机器上,执行脱机还原
./dmrman CTLSTMT="RESTORE DATABASE '/dm/data/DAMENG/dm.ini' FROM BACKUPSET '/dm/data/BACKUP_FILE_02'"
- 启动 DIsql 登录主库 A,查看备份集的 BEGIN_LSN,并从 BEGIN_LSN 开始备份主库的归档日志。(这里假设查询到的备份集 BEGIN_LSN 是 38491)
如果备份集不是在默认备份路径下,则需要先将备份集所在目录添加进来,否则会查询不到备份集信息:
SQL> SELECT SF_BAKSET_BACKUP_DIR_ADD('DISK','/dm/data');
查询备份集信息并执行备份:
SQL> SELECT BACKUP_NAME,BEGIN_LSN FROM V\$BACKUPSET;
SQL> BACKUP ARCHIVE LOG FROM LSN 38491 BACKUPSET '/dm/data/ARCH_BAK_02';
- 将归档备份集拷贝至 B 所在的机器,还原归档后、利用这些归档日志进行数据库恢复
./dmrman CTLSTMT="RESTORE ARCHIVE LOG FROM BACKUPSET '/dm/data/ARCH_BAK_02' TO ARCHIVEDIR '/dm/data/arch'"
./dmrman CTLSTMT="RECOVER DATABASE '/dm/data/DAMENG/dm.ini' WITH ARCHIVEDIR '/dm/data/arch'"
./dmrman CTLSTMT="RECOVER DATABASE '/dm/data/DAMENG/dm.ini' UPDATE DB_MAGIC"
- 重新配置 B 的 dm.ini、dmmal.ini、dmarch.ini 和 dmwatcher.ini 配置文件
- 以 Mount 方式启动 B
./dmserver /dm/data/DAMENG/dm.ini mount
- DIsql 登录 B,设置 OGUID,修改备库模式
SQL>SP_SET_PARA_VALUE(1, 'ALTER_MODE_STATUS', 1);
SQL>sp_set_oguid(82379);
SQL>alter database standby;
SQL>SP_SET_PARA_VALUE(1, 'ALTER_MODE_STATUS', 0);
上述语句中,sp_set_oguid()设置的 OGUID 值必须与主库一致。若重建的备库仍和主库在同一个集群中,则还原后备库的 OGUID 值与主库是一致的,sp_set_oguid()步骤可省略。
- 启动 B 的守护进程
./dmwatcher /dm/data/DAMENG/dmwatcher.ini
6.15 守护进程组分裂
组分裂的概念和导致分裂的场景可参考 2.2.15 组分裂一节,对于分裂的数据库需要进行人工干预,重新准备数据后,才允许重新加入守护系统。且需要手动将 dmwatcher.ctl 文件删除,否则守护进程仍然会认定本地库为分裂库。
借助监视器的 show 命令、或者 tip 命令可以查看守护系统中是否发生数据库的分裂,对于已发生的分裂,可以借助以下方法找出分裂产生的原因:
- 查看分裂库的服务器和守护进程 log 日志,查找带有“[!!!”和“!!!]”标签的 log 信息,log 信息格式形如 “[!!! LOG_INFO !!!]”,记录有数据库分裂的详细原因。
- 如果分裂库的守护进程控制文件状态不是 Valid,可借助监视器的 show open info 命令,根据 DESC 字段找出原因。
- 根据服务器、守护进程和监视器的 log 日志,找出历史操作信息,分析产生分裂的原因。
发生分裂后,用户需要选择适当的主库作为最新主库,备库采用 6.14 备库重建的方法加入系统。
6.16 dmmpp.ctl 不一致
MPP 主备环境下,在某些故障场景中,可能会出现 dmmpp.ctl 控制文件不一致的情况,可以借助监视器的 check mppctl 和 recover mppctl 命令来检测和恢复。
正常运行时,所有 MPP 主节点的 dmmpp.ctl 文件内容是完全一致的。如果某个组中的主备库实例发生改变(如执行 switchover、takeover 等),导致 dmmpp.ctl 变化,需要及时同步到所有组的主库节点上。
在执行数据同步过程中如果发生故障,导致 dmmpp.ctl 未同步,就可能造成控制文件的不一致。例如,两节点 MPP,分成两个守护进程组(GRP1 和 GRP2),组 GRP1 包含两个数据库(主库 GRP1_MPP_EP01 和备库 GRP1_MPP_EP11),组 GRP2 包含两个数据库(主库 GRP2_MPP_EP02 和备库 GRP2_MPP_EP22)。在监视器上执行 switchover 命令,将 GRP1 的两个数据库进行切换。
当执行到 switchover 流程中更新 dmmpp.ctl 文件时,可能会出现下列故障情况,导致 dmmpp.ctl 处于不一致状态。
- 更新 GRP1 的 dmmpp.ctl 文件时,监视器故障或者链路断开等原因导致更新失败,GRP1 和 GRP2 的 dmmpp.ctl 文件都没有更新,但 GRP1 的主库已经切换为 GRP1_MPP_EP11。
- 更新 GRP1 的 dmmpp.ctl 文件成功,但更新 GRP2 的 dmmpp.ctl 失败,GRP1 和 GRP2 的 dmmpp.ctl 文件不一致。
这两种不一致状态可以通过 recover mppctl 命令重新恢复到一致状态。
监视器执行 recover mppctl 的步骤如下:
- 生成新文件
根据当前守护系统中所有组的活动主库信息,重新生成有效的 dmmpp.ctl 文件。
- 检查文件一致性
检查新生成的文件和每个组当前的 dmmpp.ctl 文件是否一致,如果一致则无需恢复。
- 文件发送
将新生成的 dmmpp.ctl 文件内容依次发送给所有活动主库的守护进程,发送之前将守护进程修改为 Mppctl update 状态。再由守护进程转发至主库,主库收到后重新写入到本地的 dmmpp.ctl 文件。
注意如果存在主库故障还没有处理时,recover mppctl会跳过此故障组,只恢复存在有效主库组的dmmpp.ctl文件。故障组主库恢复正常后,需要重新执行recover mppctl进行恢复。dmmpp.ctl文件不一致时,MPP无法正常提供数据库功能。
6.17 确认监视器未启动
故障自动切换模式下,确认监视器必须一直处于启动状态,并且要确保确认监视器的配置正确(否则无法和守护进程通信,相当于确认监视器没有启动)。若确认监视器未启动或者配置错误的,在主库或备库发生故障时,无法通过确认监视器执行正常的故障处理。确认监视器的具体作用请参考 4.3 状态确认和 4.4 自动接管小节。
在没有确认监视器或确认监视器配置错误的情况下:
- 如果主库故障,则备库无法自动接管为新主库。
- 如果备库实例和备库的守护进程都出现故障,或者主备库之间出现网络故障,则主库的守护进程无法通过确认监视器来确认备库状态,主库守护进程会处于 Confirm 确认状态,实例处于 Suspend 挂起状态。
对于第 2 种情况,当备库实例和备库守护进程重新恢复正常,或者主备库之间的网络恢复正常后,并且主库守护进程 DW_FAILOVER_FORCE 配置为 1 时,即使没有确认监视器,主库的守护进程也会切换至 Failover 状态,将主库重新 Open,后续进行正常的备库恢复处理,而不会一直处于 Confirm 确认状态。
可以通过监视器的 show monitor 命令查看连接到指定守护进程的所有监视器信息,以此可以检查守护系统中是否启动有确认监视器以及确认监视器和守护进程的通信是否正常,也可以尝试再启动一个新的确认监视器,如果守护系统中已经启动有确认监视器,则不允许再启动第二个。
6.18 备库维护
守护系统正常运行时,如果需要主动维护备库,并且不启动主库的 Failover 故障处理流程,可以通过监视器命令调整主库守护进程的恢复时间间隔,并主动将备库归档失效来达到目的。
监视器提供 detach database 命令支持备库的主动维护,在备库维护完成后,可再通过 attach database 命令将备库加回到守护系统。如果在维护备库时需要将备库退出,可借助监视器的 stop database 命令来完成,维护完成后再通过 startup database 命令将备库重新启动。
假如需要动态维护的备库名称为 GRP1_RT_02,完整的维护步骤说明如下:
- 在监视器上执行 login,输入登录口令
- 在监视器上执行 detach database GRP1_RT_02,将备库分离出守护系统。
- 在监视器上执行 stop database GRP1_RT_02,将备库正常退出,如果不需要退出备库,则需要执行 stop dmwatcher database GRP1_RT_02 关闭备库的守护进程监控功能,避免将备库分离成功后,主库又发生切换,导致之前的分离操作失效,又将备库重新加回守护系统。
- 执行具体的备库维护操作。
- 备库维护完成后,如果是关闭状态,在监视器上执行 startup database GRP1_RT_02 将备库重新启动,如果已经是运行状态,根据情况看是否需要执行 startup dmwatcher database GRP1_RT_02 打开备库的守护进程监控功能。
- 待备库重新 Open 后,在监视器上执行 attach database GRP1_RT_02,将备库重新加回到守护系统中。
以上步骤中,在步骤 3 执行完成后,会将备库的守护进程切换到 Shutdown 状态,备库维护完成后,如果是用手工方式重启,需要先使用 startup dmwatcher 命令将备库的守护进程监控功能打开,备库才能自动 Open。如果是用 startup database 命令方式重启,此命令会自动将守护进程的监控功能打开。
需要注意的是,如果在分离出去的备库维护完成之前,主库故障,其他备库接管成为新主库,则之前的分离操作会失效,可以通过对备库的守护进程执行 stop dmwatcher database 关闭指定备库的监控,避免这种情况发生,或者重新对此备库执行 detach 命令,通知当前的新主库不去主动恢复正在维护中的备库。
6.19 滚动升级
数据守护 V4.0 可以确保在不中断数据库服务的情况下,实现滚动升级。
这里以一主一备的配置方式举例说明,如图 6.1 所示。
假设初始状态为:主库 DM1 部署在 DW_P 机器上,备库 DM2 部署在 DW_S 机器上,监视器部署在 DW_M 机器上,滚动升级操作步骤如下:
- 关闭监视器,升级 DW_M。重新安装新版本监视器,或者直接将新的执行程序和动态库替换旧版本,然后重启监视器;
- 关闭备库 DM2 的守护进程,正常关闭备库实例 DM2;这个过程中,主库 DM1 的守护进程会检测到备库故障,并进行故障处理,修改归档状态无效;
- 升级 DW_S,重新安装新版本服务器,或者直接将新的执行程序和动态库替换旧版本;
- 启动 DM2 实例,启动 DM2 的守护进程;
- 等待历史数据同步完成,DM2 重新加入数据守护系统(可以通过监视器 DW_M 查看数据守护系统是否恢复正常);
- 关闭主库 DM1 的守护进程,正常关闭实例 DM1;使用监视器的接管命令将 DM2 接管为新的主库。如果配置了自动接管,则预期在监视器接收主库守护进程消息超时或主库退出之后会触发自动接管;如果没有配置自动接管,或者没有成功触发自动接管,则需要手动执行接管命令;
- 升级 DW_P,重新安装新版本服务器,或者直接将新的执行程序和动态库替换旧版本;
- 启动 DM1 实例,启动 DM1 的守护进程;
- 等待历史数据同步完成,DM1 作为备库重新加入数据守护系统(可以通过监视器 DW_M 查看数据守护系统是否恢复正常);
- 在 DW_M 监视器控制台上输入 Switchover 命令,重新将 DM1 切换为主库,至此滚动升级完成。
多个备库的情况,可同样参考上面的步骤 2 到步骤 5,统一升级所有备库实例,步骤 6 中,可任意选择一个升级后的备库接管,最后升级主库完成后,再借助 switchover 命令切换主备库。
在上述滚动升级示例中,如果主库 DM1 或者备库 DM2 为 DMDSC 集群,则相应 DM1 或者 DM2 的升级步骤替换为如下步骤:
- 正常退出 DMDSC 集群中所有节点的 dmwatcher;
- 正常退出 DMDSC 集群中所有节点的 dmserver;
- 正常退出 DMDSC 集群中所有节点的 dmasmsvr;
- 正常退出 DMDSC 集群中所有节点的 dmcss;
- 升级 DMDSC 集群,重新安装新版本服务器,或者直接将新的执行程序和动态库替换旧版本;
- 启动 DMDSC 集群中所有节点的 dmcss;
- 启动 DMDSC 集群中所有节点的 dmasmsvr;
- 启动 DMDSC 集群中所有节点的 dmserver;
- 启动 DMDSC 集群中所有节点的 dmwatcher。
6.20 实时/读写分离/MPP 备库数据同步情况分析
正常情况下实时/读写分离/MPP 备库数据与主库数据基本一致,可以通过监视器的 show 命令观察主备库的 LSN 差距来大致了解数据同步情况,如果主备库的 LSN 值差距很小,说明主备库数据基本一致。当备库的 LSN 值远小于主库 LSN 值时,就需要引起重视,分析原因。
主备库 LSN 值相差很大的情况下,可以借助监视器的 show 命令查看状态来进行分析,下面的分析以守护系统中存在正常主库为前提,如果主库发生故障,是无法再向备库同步数据的,需要等主库恢复正常后,再观察主备库的 LSN 同步情况。
1. 备库的守护进程状态是否正常(WSTATUS 字段)
如果 WSTATUS 是 Error 状态,说明监视器接收备库的守护进程消息超时,需要查看守护进程是否故障。如果发生故障,则需要根据守护进程日志分析故障原因,待守护进程恢复正常后再观察备库的 LSN 增长情况。
如果 WSTATUS 是 Shutdown 状态,说明备库的守护进程监控被关闭,需要借助监视器的 startup dmwatcher 命令打开监控,打开之后再观察备库的 LSN 增长情况。
2. 备库实例状态是否正常(INST_OK 字段)
如果 INST_OK 字段是 Error 状态,说明备库的守护进程接收备库实例消息超时,需要确认备库实例是否故障。如果发生故障,则需要根据服务器日志分析故障原因,待备库恢复正常后,再观察 LSN 增长情况。
3. 备库归档状态是否有效(RSTAT 字段)
1)备库的 RSTAT 字段是 Invalid 状态
需要等主库的守护进程发起 Recovery 流程,同步主备库数据。
使用监视器的 show 命令,查看主库的守护进程状态,如果已经处于 Recovery 状态,可以使用 DIsql 登录主库查询 V$RECOVER_STATUS 视图,查看当前的恢复信息。
如果主库的守护进程不是 Recovery 状态或者 V$RECOVER_STATUS 视图中没有查到备库的恢复信息,则需要根据 Recovery 条件来判断备库是否满足恢复条件或者借助监视器的 check recover 命令来查找原因,如果不满足条件,则需要根据不满足的情况来做不同的处理。
2)备库的 RSTAT 字段是 Async_send 状态
Async_send 是同步备库和异步备库特有的归档状态,此时主库正在同步历史数据到备库,成功同步后会将备库归档状态从 Async_send 修改为 Valid 状态。
3)备库的 RSTAT 字段是 Valid 状态
如果备库归档处于有效状态,并且备库实例是 Open 状态,主库也是正常 Open 状态,则说明主备库在正常同步数据,可以通过监视器的 show 命令查看备库的 LSN 是否在持续增长,以及备库重演信息中的 N_TASK/TASK_MEM_USED 字段值来判断备库上是否有较多的日志堆积。
可以登录备库查询 V$RAPPLY_SYS/V$RAPPLY_LOG_TASK 视图来查看日志的堆积情况,备库提供有一系列的参数来控制日志堆积,具体请参考 5.1 dm.ini 小节说明。
4)备库的 RSTAT 字段是 Unknown 状态
备库需要从对应的主库上获取自己的归档状态,如果备库找不到自己的主库(没有收到过主库同步过来的日志,或者所在组中不存在活动主库,或者备库无法加入到活动主库中),则无法得知主库到自己的归档状态信息,显示为 Unknown。此时需要用户去确认是否主库故障,或者备库不满足 Recovery 条件,或者是备库已经分裂出去的情况。
6.21 异步备库数据同步情况分析
源库(主库或者异步备库)通过配置的定时器来定时同步数据到异步备库,可以根据定时器的时间间隔,使用监视器的 show 命令来观察异步备库的 LSN 是否在定期增长,或者使用监视器的 show arch send info 命令来查看源库到异步备库的数据同步情况。
如果这两种方式都没有观察到源库到异步备库的数据同步,则需要从以下几个方面来分析原因:
1. 源库是否配置正确
- 源库的 dmarch.ini 中是否有异步归档配置项,定时器名称是否配置(ARCH_TIMER_NAME),并且需要和 dmtimer.ini 中的定时器名称一致。
- 源库的数据文件目录下是否有定时器配置文件 dmtimer.ini。
- 源库的 dm.ini 中的 TIMER_INI 是否配置为 1。
- 源库的 dmmal.ini 中是否有异步备库的配置项,并且守护系统中所有实例的 dmmal.ini 的内容完全一致。
- 源库的 dmtimer.ini 中 IS_VALID 是否配置为 1。
可使用 DIsql 登录源库,查询 V$DM_ARCH_INI 和 V$DM_TIMER_INI 视图来确认配置信息是否正确。
2. 源库和异步备库状态是否正常
通过监视器的 show 命令查看源库和异步备库状态,如果源库或异步备库发生故障,则不会再同步数据,需要等两者都恢复正常后,再观察异步备库的数据同步情况。
3. 源库到异步备库的 mal 链路是否正常
通过监视器的 show arch send info 观察源库到异步备库的 MAL 链路状态,如果处于 Disconnected 状态,也无法正常同步数据,需要等链路重建成功后,再观察异步备库的数据同步情况。
4. 定时器是否满足触发条件
查看源库的 dmtimer.ini 中的触发条件,或者 DIsql 登录源库,通过 V$DM_TIMER_INI 视图查看定时器的触发条件,包括起始时间、触发频率、定时器是否启用等配置项,再根据操作系统当前时间来判断是否满足触发条件,可能会有人为修改操作系统时间或者定时器被关闭等导致定时器无法触发的情况,如果不满足触发条件,也无法同步数据到异步备库。
6.22 MPP 主备版本升级(从 V2.0 升级)
数据守护 V2.1 及以上版本,可以完全兼容实时主备和读写分离集群 V2.0 版本的配置文件,但是在 MPP 主备配置上与 V2.0 存在一定差异,因此从 V2.0 升级到更高版本时,需要修改所有 MPP 备库的 dm.ini 配置文件,将 MPP_INI 参数设置为 1,并从主库拷贝 MPP 控制文件 dmmpp.ctl 保存到备库的 ctl_path 目录。否则,数据守护从 V2.0 升级到 V2.1 及以上版本后,MPP 主备系统将无法正常运行。
6.23 MPP 主备限制登录说明
MPP 主备系统中可能会碰到登录受限的问题:[-607]:MPP 系统暂时限制用户登录。可能的场景如下:
1.配置顺序导致的。MPP 环境打开归档配置,dmarch.ini 配置实时归档,非 Mount 状态且非主备库模式(Normal),限制用户登录。原因是在 Normal 模式 Open 状态下登录后产生的日志不完整,有些 DW 类型日志只在 Primary 模式下才会生成。因此需要先配置库的主备模式后,再配置 MPP 实时归档。
2.MPP 主备系统处于切换、接管、修改 MPP_INI 参数等过程中会短暂限制用户登录。
3.MPP 主备系统中,如果切换过程中出现故障,可能导致各节点的 dmmpp.ctl 文件不一致,这种情况下会限制登录,此时需要通过监视器命令修复 mppctl 或者手动拷贝 dmmpp.ctl 文件保持一致,再对库进行重启操作。
6.24 备库查询限制说明
备库支持日志并行重演以后,各路并行重演线程分别负责重演不同的数据页,这些数据页在各路并行重演线程中重演的先后顺序是不确定的,也就是不能严格保证备库按照日志产生的顺序来修改数据页(这里指的是不同的数据页),由此会引发一些并发查询问题。
比如,主库总是先修改聚集索引,再修改二级索引,通过二级索引查询到记录,总是能在聚集索引中定位到有效数据。但是,备库开启日志并行重演后,在二级索引中查询到的记录,不一定能在聚集索引中找到相应的数据。
再比如,如果聚集索引记录对当前事务不可见,需要通过记录中的回滚记录地址 RADDR 字段,从回滚页中读取回滚记录,来进一步判断事务可见性。但是,由于数据页与回滚页的重演进度是不一致的,通过 RADDR 定位到的回滚页可能还是其他事务修改的内容。即便 RADDR 定位到的回滚页是当前事务修改的,但回滚记录内容与物理记录也不一定匹配。
另外,事务的提交顺序与这个事务修改的数据页的重演进度,也不能严格保持匹配。利用事务的状态进行可见性判断时,也存在误判的可能。
因此,对于开启并行重演的备库,无法进行记录可见性判断,只能支持 READ UNCOMMITTED 隔离级,所有读取到的记录都认为是可见的。对于未开启并行重演的备库,则保持原有处理方式,支持类 READ COMMITTED 隔离级。
为了支持备库的查询功能,重演 ROOT 页封锁等类型的日志时,会进行局部串行化处理,对备库重演性能会造成一定的影响,在备库仅用于容灾的场景下,可以考虑将备库 dm.ini 中的 REDOS_ENABLE_SELECT 设置为 0,禁止在备库上执行大部分的查询操作,配置为 0 时备库会取消部分串行化处理,能够进一步提升备库重演性能。
6.25 异步备库延时和定点重演
异步备库通过定时器定时和源库保持数据同步,每次同步数据时,源库会将本地新产生的日志全部发送给备库重演,在此基础上,还可以通过异步备库的延时和定点重演对异步备库的数据同步做进一步延时和定点限定。例如,延时重演设置为 1 小时,则主库仅会同步 1 小时前产生的日志到备库,比如重演到的时间点设置为 2021-6-4 10:30,则主库只会同步 2021-6-4 10:30 之前产生的日志到备库,之后产生的日志不会再发送到异步备库重演。
在这种模式下,异步备库始终和主库保持一段时间的日志差,此功能可在某些特定场景下发挥作用。例如,用户业务数据量很大,一旦发生了误 truncate 整张表的操作,通过备份还原方式恢复数据将会耗费很长时间,导致业务长时间中断,如果异步备库和主库之间存在一定的时间延时,在主库上数据被 truncate 以后,异步备库上还未重演,还能找到整张表数据,可以将表数据从异步备库上导出,再重新导入到主库,从而可以快速恢复主库数据,能够极大的缩短业务中断时长。
可以选择同时设置延时重演和定点重演,也可以只选择其中一项进行设置,其中延时重演通过在源库的 dmarch.ini 文件中设置 ARCH_SEND_DELAY 生效,如果源库是主库,则需要在所有备库上也进行设置,以便在主备切换后能够继续生效;定点重演功能则是通过在源库上执行系统过程或者通过执行监视器命令来动态进行设置。
下面以同时设置延时重演和定点重演功能进行举例说明:
- 修改源库的 dmarch.ini 文件,设置异步备库的延时重演时间
如果源库是主库,则需要在所有备库上也进行设置,以便在主备切换后能够继续生效。
例如,设置异步备库 GRP_LOCAL_01 延时时间为 30 分钟配置如下:
[ARCHIVE_ASYNC]
ARCH_TYPE = ASYNC #异步归档类型
ARCH_DEST = GRP1_LOCAL_01 #异步归档目标实例名
ARCH_TIMER_NAME = RT_TIMER #定时器名称,和dmtimer.ini中的名称一致
ARCH_SEND_DELAY = 30 #只发送30分钟之前产生的日志
延时配置存在以下限制:
(1)仅在异步归档配置项中支持此配置项,其他归档类型不支持。
(2)对 DMDSC 源库,建议用户在配置时保证各节点上配置的值是一致的,避免控制节点发生切换后延迟时间不一致(DMDSC 仅控制节点向异步备库发送数据)。
(3)如果 DMDSC 各节点配置在不同机器上,建议保证各机器时间一致,避免控制节点发生切换后延迟时间不一致。
(4)在实时备库或即时备库上需要同步进行配置,以便切换为主库后可以立即生效,对 DMDSC 备库,各节点也建议配置一致。
- 动态设置重演到的时间点
可通过系统过程和监视器命令方式进行设置,下面分别举例说明。
(1)通过系统过程设置
如设置异步备库 GRP_LOCAL_01 重演到 2021-6-4 10:30,则源库不再发送 2021-6-4 10:30 之后产生的日志,在源库上执行以下系统过程。
SQL>SP_SET_ARCH_SEND_UNTIL_TIME('GRP_LOCAL_01', '2021-6-4 10:30:00');
系统过程使用注意事项:
1)DSC 主库或备库修改时,仅允许在控制节点上修改。
2)仅会修改内存值,源库重启即会失效,需要重新设置。
3)指定时间串为空串时,会取消之前设置的时间点。
设置完成后,可使用系统函数查询设定的时间。
SQL>SF_GET_ARCH_SEND_UNTIL_TIME('GRP_LOCAL_01');
源库在到达定时器的定时间隔后,会根据配置的延时和定点时间信息向异步备库发送日志,如果想立即触发源库向异步备库发送日志,可通过执行以下系统过程来完成,如果源库是 DMDSC 集群,此系统过程只允许在控制节点上执行。
SQL>SP_NOTIFY_ARCH_SEND('GRP_LOCAL_01');
(2)通过监视器命令方式设置
在监视器上执行以下命令,指定异步备库 GRP_LOCAL_01 重演到 2021-6-4 10:30。
SET DATABASE GRP_LOCAL_01 UNTIL TIME 2021-6-4 10:30:00
监视器命令执行完成后,就会通知源库立即执行一次日志同步,可通过监视器 show 命令中的 APPLY_UNTIL_TIME 字段查看异步备库是否重演到了指定时间,同样的,此命令仅会修改源库中的内存值,源库重启即会失效,需要重新设置。
也可以通过监视器命令取消设置:
CANCEL DATABASE GRP_LOCAL_01 UNTIL TIME
以上全部设置完成后,在特定场景下一旦主库数据被误删除,即可借助异步备库达到快速恢复主库数据的目的。
表数据的导出及导入举例说明如下,以 TEST 表为例,使用时需要根据实际情况调整导出及导入的相关参数:
//从异步备库导出TEST表数据
dexp.exe SYSDBA/DMdba_123@192.168.0.143:32143 file=test.txt tables=(TEST) TABLE_PARALLEL=40
//导入TEST表数据到源库
dimp.exe SYSDBA/DMdba_123@192.168.0.141:32141 file=test.txt tables=(TEST) TABLE_EXISTS_ACTION=APPEND
6.26 备库归档磁盘空间不足
备库收到主库发送的日志包后,先将日志包写入归档日志文件,之后启动日志包的重演。在备库归档磁盘空间不足时(未设置归档空间上限,并且物理磁盘已经被写满),日志包写入归档日志文件的动作会被挂起,并等到人工清理出可用的磁盘空间后才会继续写入。这种情况下,此日志包的重演动作也会被挂起,而主库还在不断地发送新的日志包过来,在前一个日志包进入重演任务系统之前,这些新收到的日志包都无法进入重演流程,如果备库一直未清理出可用的磁盘空间,最终就会达到日志包堆积上限,再收到新的日志包时,就会延迟响应主库,导致主库无法再执行写操作。
针对此问题,备库提供了一个 dm.ini 参数 DW_ARCH_SPACE_CHECK 来进行检测处理,此参数配置为 1 时(默认值为 0),会对上述场景进行检测并处理,确保不影响主库的写操作,此功能目前仅支持单节点备库,DSC 备库暂不支持。
DW_ARCH_SPACE_CHECK 置为 1 时,在备库检测到本地归档磁盘空间不足时,通知本地守护进程切换为 SHUTDOWN 状态,在检测到守护进程成功切换为 SHUTDOWN 状态后,备库主动将自己关闭,随后主库发送日志失败,会短暂的进入故障处理流程(先切换到 SUSPEND 状态,再重新 OPEN),然后继续正常运行。
之所以要将备库守护进程切换为 SHUTDOWN 状态,是为了避免在备库主动关闭后又被守护进程自动拉起,再次影响到主库。
在确认备库已清理出可用的磁盘空间后,可以在监视器上执行 STARTUP DMWATCHER 命令,打开备库守护进程的监控功能,备库守护进程会自动将备库实例拉起,数据守护集群会重新恢复正常。
6.27 异步备库和实时/即时备库的动态切换
一 动态将异步归档转变为实时归档/即时归档
- 操作流程
操作流程如下:删除主备库中的异步归档;退出异步归档守护进程并修改异步归档守护进程配置;修改异步归档的归档配置;向主备库增加实时归档;重启守护进程。
须按照流程顺序严格执行。否则顺序改变可能引发不可预知的问题。例如:未按顺序严格进行,配置变更过程中可能发生主备切换,老主库认为异步备库已经变成一个实时备库,而新主库仍认为异步备库还是异步备库,引发不可预知的问题。
异步备库切换成实时备库后,主库启动 RECOVERY,有可能会进入一次短时间的 SUSPEND。
- 变更限制
(1)针对级联配置的异步备库,需要确保异步备库上配置了定时器,从而确保其变更为实时/即时备库后再切换为新主库后可以正常向之前的源库同步数据。如果级联配置的异步备库上没有配置定时器,则需要先配置定时器后才能转变为实时/即时备库。例如,现有主备环境中包含主库 A、实时备库 B、异步备库 C(源库为 A/B)和级联异步备库 D(源库为 C),针对其中的级联异步备库 D,将其变更为实时备库后有可能会切换为主库,此时需要向异步备库 C 同步数据,因此将 D 变更为实时备库前必须确保其上配置了定时器。
(2)不支持变更端口。
- 应用示例
环境主备:主库 GRP1_RT_01;实时备库 GRP1_RT_02;异步备库 GRP1_RT_03。
下面将异步备库 GRP1_RT_03 动态切换为实时备库。
- 分别连接主库 GRP1_RT_01,备库 GRP_RT_02 删除异步备库。
ALTER DATABASE DELETE ARCHIVELOG 'DEST=GRP1_RT_03';
- 退出异步备库 GRP1_RT_03 的守护进程,修改守护进程配置 DW_TYPE 为 GLOBAL,DW_MODE 为 AUTO。DW_MODE 可以根据实际情况进行调整,此处以 AUTO 为例。
DW_TYPE = GLOBAL #全局守护类型
DW_MODE = AUTO #自动切换模式
- 连接异步备库 GRP1_RT_03,修改 GRP1_RT_03 归档配置,增加 GRP1_RT_01,GRP1_RT_02 配置。
ALTER DATABASE ADD ARCHIVELOG 'DEST=GRP1_RT_01, TYPE= REALTIME';
ALTER DATABASE ADD ARCHIVELOG 'DEST=GRP1_RT_02, TYPE= REALTIME';
- 分别连接主库 GRP1_RT_01,备库 GRP1_RT_02 将异步备库 GRP1_RT_03 作为实时备库加入集群。
ALTER DATABASE ADD ARCHIVELOG 'DEST=GRP1_RT_03, TYPE= REALTIME';
- 重启 GRP1_RT_01,GRP1_RT_02,GRP3_RT_03 的守护进程,使守护进程之间可以建立连接。变更流程结束。
二 动态将实时归档/即时归档转变为异步归档
- 操作流程
操作流程如下:退出主备守护进程,删除归档配置中的实时备库,修改实时备库守护进程配置文件,修改实时备库的归档配置,启动异步备库,将异步备库加入主备的归档配置,启动主备的守护进程。
须按照流程顺序严格执行。否则顺序改变可能引发不可预知的问题。例如,未按顺序严格进行,在配置变更过程中可能发生主备切换,老主库认为实时备库已经变成一个异步备库,而新主库仍认为实时备库还是实时备库,引发不可预知的问题。
- 变更限制
不支持变更端口。
- 应用示例
环境准备:主库 GRP1_RT_01;实时备库 GRP1_RT_02;实时备库 GRP1_RT_03。
下面将实时备库 GRP1_RT_03 变为异步备库。
(1)先退出 GRP1_RT_01,GRP1_RT_02,GRP1_RT_03 的守护进程(避免 GRP1_RT_03 的守护进程与 GRP1_RT_01/GRP1_RT_02 的守护进程通信,导致监视器登记的信息不匹配。
(2)分别连接主库 GRP1_RT_01,备库 GRP1_RT_02,删除实时备库 GRP1_RT_03。
SP_SET_ARCH_STATUS('GRP1_RT_03',1);
ALTER DATABASE DELETE ARCHIVELOG 'DEST=GRP1_RT_03';
SP_SET_ARCH_STATUS 系统过程仅主库 GRP_RT_01 需要执行,备库不需要执行,作用是使备库归档失效,备库归档失效后才能执行删除语句。
如果主库是 DSC 集群,则需要分别连接主库每个节点执行 SP_SET_ARCH_STATUS 使备库归档失效,之后再在待删除备库上执行 SP_CLEAR_PKG_DEPENDS 清理正在等待依赖包的待重演日志包,避免备库上的重演操作卡住。即需要在备库上执行以下语句:
SP_CLEAR_PKG_DEPENDS();
(3)修改守护进程配置 DW_TYPE 为 LOCAL,DW_MODE 为 MANUAL。
DW_TYPE = LOCAL #本地守护类型
DW_MODE = MANUAL #手动切换模式
(4)连接 GRP1_RT_03, 修改 GRP1_RT_03 归档配置,删除实时归档,在本例子中删除 GRP1_RT_01,GRP1_RT_02 配置。
ALTER DATABASE DELETE ARCHIVELOG 'DEST=GRP1_RT_01';
ALTER DATABASE DELETE ARCHIVELOG 'DEST=GRP1_RT_02';
(5)分别连接主库 GRP1_RT_01,备库 GRP1_RT_02 将实时备库重新作为异步备库加入集群。
ALTER DATABASE ADD ARCHIVELOG 'DEST=GRP1_RT_03, TYPE= ASYNC, ARCH_TIMER_NAME =RT_TIMER‘;
(6)启动 GRP1_RT_01,GRP1_RT_02,GRP1_RT_03 的守护进程,使守护进程不会重复向 GRP1_RT_03 发送无效的连接请求。变更流程结束。
- 动态切换技巧
在进行实时备库切换到异步备库时,如果实时备库的 dmarch.ini 中有 ASYNC 归档,需要确认是否将其删除,避免此实时备库切换为异步备库后,导致其他异步备库出现多个源库的情况。需要保证切换后异步备库仅有一个源库,若存在多个给其发送归档的源库,会导致此异步备库接收日志包时出现连续性校验异常。
针对 DSC 主库的 DSC 主备环境,在将实时备库切换为异步备库时,用户需检查保证 DSC 所有节点正常,无故障节点且所有节点处于 OPEN 状态。
6.28 同步备库和实时/即时备库的动态切换
一 动态将同步归档转变为实时归档/即时归档
- 操作流程
操作流程如下:删除主备库中的同步归档,退出同步归档守护进程并修改同步归档守护进程配置,修改同步归档的归档配置,向主备库增加实时归档,重启守护进程。
须按照流程顺序严格执行。否则顺序改变可能引发不可预知的问题。例如:未按顺序严格进行,配置变更过程中可能发生主备切换,老主库认为同步备库已经变成一个实时备库,而新主库仍认为同步备库还是同步备库,引发不可预知的问题。
同步备库切换成实时备库后,主库启动 RECOVERY,有可能会进入一次短时间的 SUSPEND。
- 变更限制
不支持变更端口。
- 应用示例
环境主备:主库 GRP1_RT_01;实时备库 GRP1_RT_02;同步备库 GRP1_RT_03。
下面将同步备库 GRP1_RT_03 动态切换为实时备库。
- 分别连接主库 GRP1_RT_01 和备库 GRP_RT_02,删除同步备库。
ALTER DATABASE DELETE ARCHIVELOG 'DEST=GRP1_RT_03';
- 退出同步备库 GRP1_RT_03 的守护进程,修改守护进程配置 DW_TYPE 为 GLOBAL,DW_MODE 为 AUTO。(如果主库守护进程 DW_TYPE 为 LOCAL 且 DW_MODE 为 MANUAL,则也需要将 DW_TYPE 为 GLOBAL 并将 DW_MODE 修改为 AUTO)
DW_TYPE = GLOBAL #全局守护类型
DW_MODE = AUTO #自动切换模式
- 连接 GRP1_RT_03, 修改 GRP1_RT_03 归档配置,增加 GRP1_RT_01 和 GRP1_RT_02 配置。
ALTER DATABASE ADD ARCHIVELOG 'DEST=GRP1_RT_01, TYPE=REALTIME';
ALTER DATABASE ADD ARCHIVELOG 'DEST=GRP1_RT_02, TYPE=REALTIME';
- 分别连接主库 GRP1_RT_01 和备库 GRP1_RT_02,将 GRP1_RT_03 重新作为实时备库加入集群。
ALTER DATABASE ADD ARCHIVELOG 'DEST=GRP1_RT_03, TYPE=REALTIME';
- 重启 GRP1_RT_01、GRP1_RT_02 和 GRP3_RT_03 的守护进程,使守护进程之间可以建立连接。变更流程结束。
二 动态将实时归档/即时归档转变为同步归档
- 操作流程
操作流程如下:退出主备守护进程,删除归档配置中的实时备库,修改实时备库守护进程配置文件,修改实时备库的归档配置,启动同步备库,将同步备库加入主备的归档配置,启动主备的守护进程。
须按照流程顺序严格执行。否则顺序改变可能引发不可预知的问题。例如,未按顺序严格进行,在配置变更过程中可能发生主备切换,老主库认为实时备库已经变成一个同步备库,而新主库仍认为实时备库还是实时备库,引发不可预知的问题。
- 变更限制
- 如果变更前主库仅有一个实时归档,且后续需要将这个实时归档变更为同步归档,则重启主库守护进程前需要额外修改主库守护进程的配置文件,将 DW_TYPE 修改为 LOCAL 并将 DW_MODE 修改为 MANUAL。
- 不支持变更端口。
- 应用示例
环境准备:主库 GRP1_RT_01;实时备库 GRP1_RT_02;实时备库 GRP1_RT_03。
下面将实时备库 GRP1_RT_03 变为同步备库。
- 先退出 GRP1_RT_01、GRP1_RT_02 和 GRP1_RT_03 的守护进程。(避免 GRP1_RT_03 的守护进程与 GRP1_RT_01/GRP1_RT_02 的守护进程通信,导致监视器登记的信息不匹配)
- 分别连接主库 GRP1_RT_01 和备库 GRP1_RT_02,删除实时备库 GRP1_RT_03。
SP_SET_ARCH_STATUS('GRP1_RT_03',1);
ALTER DATABASE DELETE ARCHIVELOG 'DEST=GRP1_RT_03';
SP_SET_ARCH_STATUS 系统过程仅主库 GRP_RT_01 需要执行,备库不需要执行,作用是使备库归档失效,备库归档失效后才能执行删除语句。
如果主库是 DSC 集群,则需要分别连接主库每个节点执行 SP_SET_ARCH_STATUS 使备库归档失效,之后再在待删除备库上执行 SP_CLEAR_PKG_DEPENDS 清理正在等待依赖包的待重演日志包,避免备库上的重演操作卡住。即需要在备库上执行以下语句:
SP_CLEAR_PKG_DEPENDS();
- 修改 GRP1_RT_03 守护进程配置 DW_TYPE 为 LOCAL,DW_MODE 为 MANUAL。
DW_TYPE = LOCAL #本地守护类型
DW_MODE = MANUAL #手动切换模式
- 连接 GRP1_RT_03, 修改 GRP1_RT_03 归档配置,删除 GRP1_RT_01 和 GRP1_RT_02 配置。
ALTER DATABASE DELETE ARCHIVELOG 'DEST=GRP1_RT_01';
ALTER DATABASE DELETE ARCHIVELOG 'DEST=GRP1_RT_02';
- 分别连接主库 GRP1_RT_01 和备库 GRP1_RT_02,将 GRP1_RT_03 重新作为同步备库加入集群。
ALTER DATABASE ADD ARCHIVELOG 'DEST=GRP1_RT_03, TYPE=SYNC';
- 启动 GRP1_RT_01、GRP1_RT_02 和 GRP1_RT_03 的守护进程。变更流程结束。
6.29 注意事项
- 数据库实例、守护进程、监视器启动后,如果收不到守护进程消息,或者守护进程收不到库中实例的消息(实例处于 Error 状态),请检查端口、OGUID 等配置,并确认是否消息被防火墙屏蔽。
- 数据库实例、守护进程和监视器应用同一个用户启动,避免出现权限问题引发系统异常。
- 手动方式启动数据守护系统时,对于守护进程、数据库实例和监视器的启动顺序没有严格要求,但手动方式退出数据守护系统时,一定要严格按照 6.4 关闭数据守护系统小节中描述的顺序来操作,否则会导致主库异常关闭。
- 如果 DMDSC 集群使用了 ASM 文件系统,则守护进程启动时必须等待 ASM 文件系统准备完成,即 dmasmsvr 服务启动完成,否则无法正常访问共享存储上的 dmwatcher.ctl 文件,在 dmasmsvr 服务启动完成之前,守护进程的启动会一直处于等待状态。
- DMDSC 集群如果作为备库配置在守护系统中,那么在配置源库的 dmarch.ini 时,要将 DMDSC 备库作为一个整体配置在同一个归档配置项中,DMDSC 备库的所有节点实例名以“/”分隔开作为一个 ARCH_DEST 进行配置,具体的配置示例请参考 7.5.1 配置说明小节。
- DMDSC 集群存在一些特殊场景处理,比如在 Mount 或 Suspend 状态下启动故障处理或故障重加入时会主动宕机,守护进程在某些特定场景下也会主动宕机,具体的场景说明请参考 2.7.8 故障场景说明小节。
- 备库故障重启,主库同步归档日志失败,可以通过监视器的 show arch send info 命令查看 Recovery 的历史同步信息,或者查看主库、备库的数据库日志信息、守护进程日志信息,检查失败原因。如果是主库归档日志不完整,或者主备库日志不连续等原因造成同步失败,则需要尽快重建备库。
- 建议使用故障手动切换模式数据守护系统。如果配置为故障自动切换模式,则必须配置确认监视器。
- 同时配置数据守护和高可靠集群(HIGH-AVAILABILITY,简称 HA)软件情况下,需要将 dmwatcher.ini 的 INST_AUTO_RESTART 设置为 0,避免 dmwatcher 与 HA 软件同时启动 dmserver 实例。同时,配置 dm.ini 中的 HA_INST_CHECK_IP/HA_INST_CHECK_PORT 参数,避免由于 HA 软件故障,引发多个 dmserver 实例同时操作一份数据,导致数据损坏。
- 配置异步备库时,如果异步备库的源库是实时主库或即时主库,则需要在所有的实时备库或即时备库上配置相同的异步归档配置项、定时器等,以确保主备库发生切换后可以继续向异步备库同步数据。
- 用户应该使用“正常接管”方式将备库切换为主库,在无法正常接管的情况下,再考虑使用“强制接管”方式,但“强制接管”前一定要确认主备库数据是一致的,避免引发组分裂。
- 根据磁盘空间情况,合理设置 dmarch.ini 的 ARCH_SPACE_LIMIT 值,防止磁盘空间被归档日志文件占满。需要注意的是,如果主库是 DSC 集群,则备库本地的归档文件是按照主库节点号分别存放的,每个主库节点在备库的本地归档文件大小不会超过 ARCH_SPACE_LIMIT 限制,因此备库总的归档文件空间占用很有可能超出 ARCH_SPACE_LIMIT 值,建议备库按 DSC 集群节点数 * ARCH_SPACE_LIMIT 预留足够的本地归档磁盘空间。
- 备库重做新建数据库文件操作时,缺省按照主库的目录进行创建,如果创建失败则会将文件创建到 dm.ini 中指定的 system_path 目录下。
- DM 根据 dm.ini 参数 TS_MAX_ID/TS_FIL_MAX_ID 分配表空间和文件对象内存存放空间,用户需要确保主备库参数一致。如果配置不一致,比如:主库 TS_MAX_ID > 备库 TS_MAX_ID、并且新建表空间 ID > 备库 TS_MAX_ID 情况下,主库创建表空间成功,备库重演创建表空间操作时检测到 ID 越界会强制退出系统。
- 守护进程通过当前系统时间与最后一次接收消息时间的差值,来检测目标对象是否异常,因此,修改操作系统时间可能会导致误判系统出现故障,不建议在数据守护系统运行过程中调整操作系统时间。
- 默认配置下,主备库都允许执行表空间脱机(offline)操作,并且主库的表空间脱机操作不会同步到备库。如果用户直接登录备库进行表空间脱机操作,重做 Redo 日志访问此表空间将导致备库强制退出。因此,针对备库的表空间脱机操作要十分谨慎。用户可以修改 dm.ini 配置参数 ENABLE_OFFLINE_TS = 2,限制备库表空间脱机操作,降低误操作概率。
- 主库上新建表空间或增加文件等操作,当备库磁盘空间不足时,备库上重做日志会导致宕机。
- MPP 主备交叉配置的环境中,创建表空间必须使用相对路径。例如,CREATE TABLESPACE TS4 DATAFILE 'TS4.DBF' SIZE 128。
- 为了防止备库上重演日志堆积太多、占用大量内存、备库重演无响应导致主库挂住不能提供服务等情况的发生,可通过适当调整 BUFFER、REDOS_BUF_SIZE、REDOS_BUF_NUM、REDOS_MAX_DELAY 这几个参数达到加快备库重演速度、达到设置的堆积上限后延迟响应主机、备库自动宕机等目的。其中 REDOS_BUF_SIZE 和 REDOS_BUF_NUM 同时起作用,只要达到一个条件即延迟响应。
- 备库支持索引监控,主备库可以分别设置不同的索引监控。备库还支持查询 V$动态视图、执行获取和修改 INI 参数的系统函数以及执行备份相关的系统函数。需要注意的是,若是读写分离集群,以通常的登录名方式登录并执行上述操作可能会引发不确定性,操作可能在备库执行也可能在主库执行,建议使用 LOCAL 方式登录指定的数据库进行操作。
- 主库使用 SP_SET_PARA_VALUE 系统过程修改 INI 参数时,不会生成 Redo 日志,因此此操作不会通过日志同步到备库。如果备库配置了 INI 参数 INI_SYNC=1 时,当主库修改 INI 参数后,备库每隔一段时间会自动从主库同步相应的参数修改。
- 从数据守护 V3.0 开始,允许备库执行创建、扩展日志文件,备库不再重演主库创建、扩展日志文件产生的日志,因此主库扩展日志文件后,也需要手动对备库扩展日志文件,以免备库出现日志环冲破的情况。
- 主库执行 CREATE TABLESPACE 创建表空间、ALTER TABLESPACE ADD DATAFILE 表空间加文件、重命名文件等操作时,会将主库的文件路径信息写入到 Redo 日志中。备库重做这些 Redo 日志时,在备库创建相应的文件。备库创建文件的规则如下:
(1)主库指定的是绝对路径,备库优先在相同目录下创建文件;
(2)主库指定是相对路径,备库使用 dm.ini 配置文件中的 system_path 和主库指定的文件名进行拼装,转换为绝对路径。这一步骤中,如果 system_path + file_name 的总长度超过 256 个字节,文件路径拼接失败,系统会强制退出。
(3)尝试创建文件,如果文件创建失败,则尝试在 system_path 目录下创建文件;如果仍然创建失败,则重命名文件,继续尝试在 system_path 目录下创建文件。如果连续重试 3 次仍然失败,则备库会强制退出。