credspp数据库修正,DM7 达梦 数据库 数据守护(Data Watch) (2) -- 主备类型

在上节我们看了数据守护的基本概念,如下:

DM7 达梦 数据库 数据守护(Data Watch) (1) — 基本概念

https://www.cndba.cn/dave/article/3665

本篇我们来看下DW的主备类型。

1 DW类型概述

DM的DW解决方案有三种类型的主备类型:

https://www.cndba.cn/dave/article/3666

实时主备

由一个主库以及一个或者多个配置了实时(Realtime)归档的备库组成,其主要目的是保障数据库可用性,提高数据安全性。实时主备系统中,主库提供完整的数据库功能,备库提供只读服务。主库修改数据产生的Redo日志,通过实时归档机制,在写入联机Redo日志文件之前发送到备库,实时备库通过重演Redo日志与主库保持数据同步。当主库出现故障时,备库在将所有Redo日志重演结束后,就可以切换为主库对外提供数据库服务。

MPP主备

就是在MPP集群的基础上,为每一个MPP节点配置一套实时主备系统,这些实时主备系统一起构成了MPP主备系统。我们将一个MPP节点对应的主备系统称为一个数据守护组(Group),MPP主备系统中各个数据守护组保持相对独立,当某个MPP主节点出现故障时,在其对应的数据守护组内挑选一个备库切换为主库后,就可以确保整个MPP集群的正常使用。https://www.cndba.cn/dave/article/3666

读写分离集群

由一个主库以及一个或者多个配置了即时(Timely)归档的备库组成,其主要目标是在保障数据库可用性基础上,实现读、写操作的自动分离,进一步提升数据库的业务支撑能力。读写分离集群通过即时归档机制保证主、备库数据一致性,并配合达梦数据库管理系统的各种接口(JDBC、DPI等),将只读操作自动分流到备库,有效降低主库的负载,提升系统吞吐量。

2 实时主备

实时主备系统由主库、实时备库、守护进程和监视器组成。通过部署实时主备系统,可以及时检测并处理各种硬件故障、数据库实例异常,确保持续提供数据库服务。

2.1 主要功能

1. 实时数据同步

主备库通过实时归档完成数据同步,实时归档要求主库将 RLOG_BUF 发送到备库后,再将 RLOG_BUF 写入本地联机 Redo 日志文件。但要注意的是,备库确认收到主库发送的Redo 日志,并不保证备库已经完成重演这些 Redo 日志,因此主备库之间的数据同步存在一定的时间差。

2. 主备库切换

主备库正常运行过程中,可以通过监视器的 Switchover 命令,一键完成主备库角色转换。主备库切换功能可以确保在软、硬件升级,或系统维护时,提供不间断的数据库服务。

3. 自动故障处理

备库故障,不影响主库正常提供数据库服务,守护进程自动通知主库修改实时归档为Invalid 状态,将实时备库失效。

4. 自动数据同步

备库故障恢复后,守护进程自动通知主库发送归档 Redo 日志,重新进行主备库数据同步。并在历史数据同步后,修改主库的实时归档状态为 Valid,恢复实时备库功能。

备库接管后,原主库故障恢复,守护进程自动修改原主库的模式为 Standby,并重新作为备库加入主备系统。

5. 备库接管

主库发生故障后,可以通过监视器的 Takeover 命令,将备库切换为主库,继续对外提供服务。如果配置为自动切换模式,确认监视器可以自动检测主库故障,并通知备库接管,这个过程不需要人工干预。

6. 备库强制接管

如果执行 Takeover 命令不成功,但主库可能由于硬件损坏等原因无法马上恢复,为了及时恢复数据库服务,DM 提供了 Takeover Force 命令,强制将备库切换为主库。但需要由用户确认主库故障前,主库与接管备库的数据是一致的(主库到备库的归档是 Valid状态),避免引发守护进程组分裂。

执行 Takeover Force 有可能引发组分裂,而 Takeover 命令是在确保不会产生组分裂情况下才允许执行。

https://www.cndba.cn/dave/article/3666

https://www.cndba.cn/dave/article/3666

2.2 归档流程

实时归档是实时主备数据同步的基础,其流程如下图所示:

20bbc99678714e36425a879c4a353cae.png

主库生成联机 Redo 日志,当触发日志写文件操作后,日志线程先将 RLOG_BUF 发送到备库,备库接收后进行合法性校验(包括日志是否连续、备库状态是否 Open 等),不合法则返回错误信息,合法则作为 KEEP_BUF 保留在内存中,原有 KEEP_BUF 的 Redo 日志加入 Apply 任务队列进行 Redo 日志重演,并响应主库日志接收成功。

2.3 Huge 表日志

Huge 表的存储使用独立的存储机制,分别存储在数据文件和辅助表中。数据文件存放数据;辅助表存放控制信息。数据文件不以数据页作为 IO 基本单位,数据修改不产生常规的 Redo 日志;而辅助表是一个普通的使用数据页存储的表,数据修改会产生 Redo 日志。

数据区是 Huge 表存储的基本单位,一个数据区存储 Huge 表单列数据的若干行。每个Huge 表还对应有一个辅助表,用来管理以及辅助系统用户操作 Huge 表数据。

Huge 表一个数据区的刷盘,包含两个动作:1)数据区写入数据文件;2)写入辅助表信息。所以,Huge 表的归档流程与一般归档流程不同,包括以下步骤:

数据区数据写入数据文件前,先通过 MAL 系统发送给备库,并等待备库响应;

备库收到数据区数据后,先进行缓存,再响应主库;

主库收到备库响应后,将数据区数据写入数据文件;

主库所有需要刷盘的数据区都完成上述 1~3 步骤后,生成一个 Redo 日志,标记Huge 表数据区刷盘动作;

主库更新辅助表信息,由于辅助表是普通表,因此更新过程正常生成 Redo 日志;

主库触发 Redo 日志刷盘,先将日志发送到备库,等待备库响应后再写入本地联机Redo 日志文件中;

备库重做 Huge 表数据刷盘 Redo 日志时,将之前缓存的数据区数据写入数据文件;

备库随后重做更新辅助表的 Redo 日志。

当备库故障恢复后,同步 Huge 表历史数据的流程也与普通表存在一些差异,步骤如下:https://www.cndba.cn/dave/article/3666

备库初始化环境,清理所有数据区数据缓存;

主库向备库发送本地归档日志;

备库重做日志,做到 Huge 表数据区刷盘日志时,缓存对应 Huge 表 ID、数据区号等信息,辅助表相关的 Redo 日志正常重做;

主、备库同步历史归档完成后,守护进程增加了一个步骤,通知主库发送 Huge 表数据:

1) 主库从备库获取需要同步的 Huge 表 ID、数据区号等信息;

2) 主库根据这些信息,读取对应的数据区数据,并发送给备库;

3) 对于每个数据区,备库接收到数据区后,将其写入到对应的数据文件中,写入完成后发送确认消息给主库;主库在收到确认消息后再发送下一个数据区的数据;

4) 主库完成所有数据区的数据发送后,通知备库数据发送完成;

5) 备库接收到数据发送完成的消息后,清理之前缓存的 Huge 表 ID、数据区号信息;

6) 主库通知守护进程 Huge 表数据文件的恢复完成。

数据同步完成。

在同步数据过程中,备库只有在收到主库发来的所有 Huge 表数据都发送完成的消息后才会清理缓存的 Huge 表 ID、数据区号信息。如果在同步数据过程中备库再次故障,这些缓存没有被清理,备库重启需要重新同步这些数据。

3 MPP 主备

MPP 主备就是在 MPP 集群的基础上,为每一个 MPP 节点配置一套实时主备系统,这些实时主备系统一起构成了 MPP 主备系统。MPP 主备系统包含多个守护进程组,每个守护进程组都是一个相对独立的实时主备系统,具备实时主备的基本功能,可以进行主备切换、备库接管等操作。

MPP 主备的主要目的是为 DM MPP 集群提供数据可靠性保障,备库只做数据容灾、备份,MPP 备库并不是 MPP 集群的一部分,只是某个 MPP 节点(主库)的镜像。MPP 备库不参与 MPP 操作,与其他 MPP 备库之间也没有任何关系,MPP 备库只能以单节点方式提供只读服务,但不提供全局的 MPP 只读服务。

MPP 主备系统中,一个守护进程 dmwatcher 可以监控、管理多个守护进程组的数据库实例。一般来说,一台物理机器上,可以部署 1 个 MPP 节点的主库和多个其他 MPP 节点的备库,充分利用硬件资源,节省投资。

数据守护 V2.1 中,Global 守护类型的 MPP 主备库都需要在 dm.ini 中配置 MPP_INI为 1,并且 MPP 主备库的本地数据文件目录下都需要有 dmmpp.ctl 文件,如果 Global守护类型的备库没有上述配置,守护进程和监视器无法正常使用,守护进程会切换到Shutdown 状态,监视器上无法正常执行命令,会打印配置不一致的提示信息。

下图以三个 MPP 节点,每个节点配备两个备库为例,说明 MPP 主备系统的结构。

61d6cc05e888d1769d83e0ac4a1a6792.pnghttps://www.cndba.cn/dave/article/3666

3.1 功能扩展

与实时主备系统相比,MPP 主备扩充了维护 MPP 控制文件功能,dmmpp.ctl 控制文件记录了 MPP 集群的节点信息,在主备库切换、或者备库接管后,必须将新的主库信息更新到 dmmpp.ctl 文件中。

273c522f3485f25c9b2ecae433cf2bfe.png

3.2 dmmpp.ctl 维护

dmmpp.ctl 控制文件的信息主要包括:系统状态、MPP 节点数、文件校验码、故障节点数、故障节点序号、配置项名、实例名、实例节点序号,以及根据节点数和实例序号生成的哈希映射数组等。MPP 集群中节点间的关联信息记录在 dmmpp.ctl 控制文件中,因此,所有 MPP 主节点存放的 dmmpp.ctl 文件内容要求完全一致。

MPP 主备系统中,要求所有节点(包括主库和备库)的 ctl_path 目录保存一份dmmpp.ctl 控制文件,并要求将所有节点的 dm.ini 参数 MPP_INI 配置为 1,以确保 MPP主备系统正常运行。 当 MPP 主备系统中,某个守护进程组的主节点发生变化(切换或接管),监视器会通知所有主节点更新本地 dmmpp.ctl 文件,确保所有主节点 dmmpp.ctl 控制文件始终保持一致。

当 MPP 主备系统中所有主节点都故障,需要进行强制接管时,守护进程会根据备库上的 dmmpp.ctl 文件,重新构造完整、有效的 dmmpp.ctl 内容,并最终更新新主库的dmmpp.ctl 文件。https://www.cndba.cn/dave/article/3666

执行 MPP 主备库切换操作,需要修改所有节点的 dmmpp.ctl 文件,将新主库实例名替换原主库实例名。比如 0 号节点发生切换,只要将 0 号节点对应的 mpp_inst_name 修 改为新主库的实例名。

以上图的 MPP 主备系统为例,说明一个节点主备切换时相应的控制文件是如何变化的。由于 dmmpp.ctl 是二进制文件,为了便于识别,下面列出的是对应转换的文本格式内容。

原始配置如下:

[service_name1] #配置项名

mpp_seq_no = 0 #节点序号

mpp_inst_name = EP0 #节点实例名

[service_name2]

mpp_seq_no = 1

mpp_inst_name = EP1

[service_name3]

mpp_seq_no = 2

mpp_inst_name = EP2

将 EP0 和 EP0’切换后,dmmpp.ctl 中对应的实例信息如下,可以看出配置项中只有节点实例名 EP0 变化为 EP0’了,节点序号以及其他配置项的内容都保持不变:

[service_name1] #配置项名

mpp_seq_no = 0 #节点序号

mpp_inst_name = EP0' #节点实例名

[service_name2]

mpp_seq_no = 1

mpp_inst_name = EP1

[service_name3]

mpp_seq_no = 2

mpp_inst_name = EP2

MPP 集群中用户登录某个节点创建一个会话(session)时,系统自动在其他 MPP 节点上建立对应的镜像会话(msession),会话断开时,系统自动通知其他 MPP 节点释放对应会话(镜像会话)。MPP 主备切换时,整个 MPP 集群的所有连接被强制断开、所有会话被强制释放、并且切换过程中新的连接请求会被阻塞。主备切换完成后,连接请求会被分配到新的主节点上。

4 读写分离集群

读写分离集群是基于即时归档实现的高性能数据库集群,不但提供数据保护、容灾等数据守护基本功能,还具有读写操作自动分离、负载均衡等特性。读写分离集群最多可以配置8 个即时备库,提供数据同步、备库故障自动处理、故障恢复自动数据同步等功能,也支持自动故障切换和手动故障切换两种守护模式。

一般情况下,应用系统中查询等只读操作的比例远大于 Insert/Delete/Update 等DML 操作,修改对象定义等 DDL 操作的比例则更低。但是,这些操作往往混杂在一起,在高并发、高压力情况下,会导致数据库性能下降,响应时间变长。借助读写分离集群,将只读操作自动分发到备库执行,可以充分利用备库的硬件资源,降低主库的并发访问压力,进而提升数据库的吞吐量。

读写分离集群不依赖额外的中间件,而是通过数据库接口与数据库之间的密切配合,实现读、写操作自动分离特性。DM 的 JDBC、DPI、DCI、ODBC、Provider 等接口都可以用来部署读写分离集群。

根据是否满足读提交事务隔离级特性,读写分离集群可以配置为事务一致模式和高性能两种模式。简单的说,事务一致模式下,不论一个 Select 语句是在备库执行、还是在主库执行,其查询结果集都是一样的。高性能模式则不能保证查询是一致的,备库的数据与主库的数据同步存在一定的延迟,当 Select 语句发送到备库执行时,返回的有可能是主库上一个时间点的数据。

4.1 归档流程

读写分离集群的实现基础是即时归档。即时归档流程与实时归档流程存在一定差异:

主库先将日志写入本地联机 Redo 日志文件中,再发送 RLOG_BUF 到备库。

备库日志重演时机有两种选择:

 事务一致模式 要求备库在重演 Redo 日志完成后再响应主库。

 高性能模式 与实时归档一样,收到 Redo 日志后,马上响应主库。

即时归档的同步机制,可以保证备库的 Redo 日志不会比主库的 Redo 日志多,因此即时备库不需要 KEEP_BUF,收到 RLOG_BUF 直接加入到 Apply 任务系统,启动 Redo日志重演。

备库故障、或者主备库之间网络故障,导致发送 RLOG_BUF 失败后,主库马上修改即时归档为 Invalid 状态,并切换数据库为 Suspend 状态。

即时归档修改为 Invalid 状态后,会强制断开对应该备库上存在影子会话的用户会话,避免只读操作继续分发到该备库,导致查询数据不一致。

0959579a8ed77e6ae5bc7343ed8bd60c.png

4.2 实现原理

实现读写分离集群的基本思路是:利用备库提供只读服务、无法修改数据的特性,优先将所有操作发送到备库执行,一旦备库执行报错,则发送到主库重新执行。通过备库“试错”这么一个步骤,自然地将只读操作分流到备库执行。并且,备库“试错”由接口层自动完成,对应用透明。https://www.cndba.cn/dave/article/3666

读写分离集群数据库连接创建流程:

用户发起数据库连接请求。

接口(JDBC、DPI 等)根据服务名配置(dm_svc.conf)登录主库。

主库挑选一个有效即时备库的 IP/Port 返回给接口。

接口根据返回的备库 IP 和 Port 信息,向备库发起一个连接请求。

备库返回连接成功信息。

接口响应用户数据库连接创建成功。

接口在备库上创建的连接,是读写分离集群自动创建的;对用户而言,就是在主库上创建了一个数据库连接。下面以配置了两个备库的读写集群为例,说明读写分离集群的连接创建流程。

a13de72ede5dd5436cd41520c8afd621.png

读写分离集群语句分发流程:

接口收到用户的请求。

接口优先将 SQL 发送到备库执行。

备库执行并返回执行结果。如果接口收到的是备库执行成功消息,则转到第 6 步,如果接口收到的是备库执行失败消息,则转到第 4 步。

重新将执行失败的 SQL 发送到主库执行。只要第 3 步中的 SQL 在备库执行失败,则同一个事务后续的所有操作(包括只读操作)都会直接发送到主库执行。

主库执行并返回执行结果给接口。一旦主库上执行的写事务提交,则下次继续从第1 步开始执行。

接口响应用户并将执行结果返回给用户。

5bc26af1d5b164c958e890f674c59612.png

执行举例说明:

--数据准备

create table t(c1 int);

--事务开始

select * from t; --首先在备库上执行

insert into t values(1); --写操作转移到主库上执行

select * from t; --事务未提交,还在主库上执行

commit; --事务提交

select * from t; --事务已提交,重新转移到备库上执行

4.3 事务一致性

读写分离集群通过 JDBC、DPI 等接口自动分发语句,一个事务包含的多个语句可能分别在备库和主库上执行,但执行结果与单独在一个数据库实例上完全一致,满足读提交事务隔离级特性。

下面以两段伪代码 trx1 和 trx2 为例,说明读写分离的特性和如何实现事务隔离级。

trx1:

update t set c1 = 2;

commit;

trx2:

rs = select c1 from t;

fetch c1 from rs into var_x;

insert into tx values(var_x);

commit;

根据读写分离特性,trx1 的 update 在主库执行;trx2 的 select 语句在备库执行,insert 语句转到主库执行,并且 trx2 的 insert 语句的插入值,是从之前执行的 select结果集中获取。

下面根据即时归档流程,结合 trx2 执行 select 语句时机和以及 trx1 的不同状态进行讨论,详细地说明读写分离集群是如何实现提交事务隔离级别的。

第一种情况,trx2 执行 select 时,trx1 的 commit 还未执行。

trx2 的 select 语句,不管是在主库还是备库执行,查询结果都是 trx1 更新 t 表之前的值,var_x = 1。

第二种情况,trx2 执行 select 时,trx1 的 commit 已经执行完成。

trx2 的 select 语句,不管是在主库还是备库执行,查询结果都是 trx1 更新 t 表后的值,var_x = 2。

第三种情况,trx2 执行 select 时,trx1 正在执行 commit。

trx2 的 select 查询结果,与两个语句在系统内部的执行顺序有关,var_x 的值可能是 1 或者 2。但由于 trx1 的 commit 并没有明确响应用户,var_x 的最终值取决于数据库管理系统的实现策略,不管返回 1 还是 2,都符合读提交事务隔离级。

为了保证主备库上的一致性,目前读写分离集群有下列一些类型的语句不会在备库上执行,都在主库上执行:

设置会话、事务为串行化隔离级语句。

表对象上锁语句(lock table xx in exclusive mode)。

查询上锁语句(select for update)。

备份相关系统函数(由于备份文件放在主库上,备库查询不到)。

自治事务操作(内部可能有提交操作)。

包操作(比如有些操作将文件创建在备库上,主库上后续找不到)。

动态视图查询(和上下文相关,主备库上可能不一样)。

设置自增列操作语句(SET IDENTITY_INSERT TABLE ON)。

临时表查询(临时表不产生日志)。

SF_GET_PARA_STRING_VALUE、SF_GET_PARA_DOUBLE_VALUE 等函数。

读写分离集群中,当一个 SQL 从备库切换到主库执行时,主库会启动一个新的事务,主库事务与备库事务没有任何联系,事务 ID 也完全不同。备库事务ID 与主库事务 ID 分配机制并不相同,主库的事务 ID 取值范围是[1 ~ 0x7FFFFFFFFFFF],备库事务 ID 取值范围是 [0x800000000000 ~ 0xFFFFFFFFFFFF];备库事务 ID 是一个内存值,每次重启后都从0x800000000000 开始重新分配;主库事务 ID 是一个物理值,一旦分配后,就不会再重复分配。

4.4 性能调整

根据读写分离语句分发流程可以发现,当一个应用系统中,只读事务占绝大多数情况下,可能出现备库高负载、高压力,主库反而比较空闲的情况。为了实现负载均衡,更好的利用主备库的硬件资源,JDBC 等数据库接口提供了配置项,允许将一定比例的只读事务分发到主库执行。因此,用户应该根据主备库的负载情况,灵活调整接口的分发比例 rwPercent配置项,以获得最佳的数据库性能。

https://www.cndba.cn/dave/article/3666

备库数量是影响读写分离集群性能的一个重要因素,备库越多则每个备库需要承担的任务越少,有助于提升系统整体并发效率。另外,事务一致模式下,主库要等所有备库重演Redo 日志完成后,才能响应用户,随着备库的增加,即时归档时间会变长,最终降低非只读事务的响应速度。因此,部署多少备库,也需要综合考虑硬件资源、系统性能等各种因素。

配置为高性能模式,则是提升读写分离集群的另一个有效手段。如果应用系统对查询结果实时性要求并不太高,并且事务中修改数据的操作也不依赖同一个事务中的查询结果。那么,通过修改 dmarch.ini 中的 ARCH_WAIT_APPLY 配置项为 0,将读写分离集群配置为高性能模式,可以大幅提高系统整体性能。

如果应用包含以下代码逻辑,则不适合使用高性能模式:

--tx1 事务开始

insert into t values(1); --写操作在主库上执行

commit; --事务提交

--tx2 事务开始

select top 1 c1 into var1 from t; --tx1 事务已提交,select 操作重新转移到备库上执行。高性能模式下备库可能还没有重做日志,查不出 tx1 中插入的结果

update t set c1 = var1 + 1 where c1 = var1; --更新不到数据

此外,根据读写分离特性,合理的规划应用的事务逻辑,也可以获得更佳的性能:

尽可能将事务规划为只读事务和纯修改事务,避免无效的备库试错。

读操作尽量放在写操作之前,用备库可读的特点来分摊系统压力。

5 异步备库

异步备库一般用于历史数据统计、周期报表等对数据实时性要求不高的业务场合。异步归档时机可以选择在源库空闲的时候,可避免源库的业务高峰期同步数据对性能的影响。

每个 Primary 或者 Standby 模式的库,都可以配置最多 8 个异步备库。配置了异步备库的 Primary 或者 Standby 模式的库,统称为源库。可以在实时主备、MPP 主备和读写分离集群的主库和备库上配置异步备库,异步备库可级联配置,异步备库本身也可以作为源库配置异步备库。理论上守护系统中可配置的异步备库的数目只受 MAL 系统最大节点数(2048)的限制,但监视器上最多监视 16 个异备。

一个异步备库只能有一个源库,这个限制由用户在配置时保证。配置异步备库十分简单,确保源库和异步备库之间的 MAL 链路是正常的,在源库的 dm.ini 中打开定时器TIMER_INI 开关,同时配置文件 dmtimer.ini,由定时器定时触发源库发送归档日志到异步备库即可。异步归档的最小触发间隔是 1 分钟。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值