• [版主交流] 图片竟然要求本地上传,真是out得很啊,期待快些改进
    图片竟然要求本地上传,真是out得很啊,期待快些改进
  • [技术解读] GaussDB数据库修改同步备机数量
    GaussDB数据库修改同步备机数量背景说明当前使用的测试环境为GaussDB主备集群1主3备1仲裁共5个节点,由于测试的需要,现需要把同步备的数量修改为1。操作步骤1、根据当前的版本,如果裸金属部署版本大于等于503.2版本且需要把synchronous_standby_names的参数修改为any1或first1,需要修改enable_az_auto_switchover参数为0,否则不需要修改该参数,跳过该步骤enable_az_auto_switchover参数说明:AZ自动切换开关,若打开,则表示允许cm_server自动切换AZ。否则当发生dn故障等情况时,即使当前AZ已经不再可用,也不会自动切换到其它AZ上,除非手动执行切换命令。取值范围:非负整型,0或1,0表示开关关闭,1表示开关打开。修改后可以reload生效,参数修改请参考表14-2进行设置。默认值:1gs_guc reload -Z cmserver -N all -I all -c "enable_az_auto_switchover"="0"2、查询当前synchronous_standby_names参数在各个DN节点的配置synchronous_standby_names,当前集群该参数默认为ANY 2参数说明:潜在同步复制的备机名称列表,每个名称用逗号分隔。当前连接的同步备机是列表中的第一个名称。如果当前同步备机失去连接,则它会立即更换下一个优先级更高的备机,并将此备机的名称放入列表中。备机名称可以通过设置环境变量PGAPPNAME指定。取值范围:字符串。当取值为*,表示匹配任意提供同步复制的备机名称。支持按如下格式配置:● ANY num_sync (standby_name [, …]) [, ANY num_sync (standby_name [, …])]● [FIRST] num_sync (standby_name [, …])● standby_name [, …]说明1.其中num_sync是事务需要等待其回复的同步复制的备机的数量,standby_name是备机的名称,FIRST以及ANY指定从所列服务器中选取同步复制的备机的策略。2.ANY N (dn_instanceId1, dn_instanceId2,…)表示在括号内任选N个主机名称作为同步复制的备机名称列表。例如,ANY 1(dn_instanceId1, dn_instanceId2)表示在dn_instanceId1和dn_instanceId2中任选一个作为同步复制的备机名称。3.FIRST N (dn_instanceId1, dn_instanceId2,…)表示在括号内按出现顺序的先后作为优先级选择前N个主机名称作为同步复制的备机名称列表。例如,FIRST 1 (dn_instanceId1,dn_instanceId2)表示选择dn_instanceId1作为同步复制的备机名称。4.dn_instanceId1, dn_instanceId2,…和FIRST 1 (dn_instanceId1, dn_instanceId2,…)具有的含义相同。[omm@ZHHALxjspo0db009 ~]$ gs_guc check -Z datanode -N all -I all -c "synchronous_standby_names" The gs_guc run with the following arguments: [gs_guc -Z datanode -N all -I all -c synchronous_standby_names check ]. Total GUC values: 4. Failed GUC values: 0. The details for synchronous_standby_names: [103.X.X.171] synchronous_standby_names='ANY 2(dn_6002,dn_6003,dn_6004)' [/data/data/dn/dn_6001/postgresql.conf] [103.X.X.172] synchronous_standby_names='ANY 2(dn_6001,dn_6003,dn_6004)' [/data/data/dn/dn_6002/postgresql.conf] [103.X.X.173] synchronous_standby_names='ANY 2(dn_6004,dn_6001,dn_6002)' [/data/data/dn/dn_6003/postgresql.conf] [103.X.X.174] synchronous_standby_names='ANY 2(dn_6003,dn_6001,dn_6002)' [/data/data/dn/dn_6004/postgresql.conf] 3、根据查询节点的配置然后修改命令并分别在对应节点执行如下命令--DN1节点执行 gs_guc reload -Z datanode -D /data/data/dn/dn_6001 -N 103.161.73.171 -c "synchronous_standby_names='ANY 1(dn_6002,dn_6003,dn_6004)'" --DN2节点执行 gs_guc reload -Z datanode -D /data/data/dn/dn_6002 -N 103.161.73.172 -c "synchronous_standby_names='ANY 1(dn_6001,dn_6003,dn_6004)'" --DN3节点执行 gs_guc reload -Z datanode -D /data/data/dn/dn_6003 -N 103.161.73.173 -c "synchronous_standby_names='ANY 1(dn_6004,dn_6001,dn_6002)'" --DN4节点执行 gs_guc reload -Z datanode -D /data/data/dn/dn_6004 -N 103.161.73.174 -c "synchronous_standby_nam作者:墨竹
  • [其他] 使用TaurusDB完成数据查询操作,回复正确的查询截图即可参与抽奖!
    【任务背景】某公司为自己新上市的产品运营投入了30000元,现在需要分析用户行为数据和充值情况计算投入产出比(ROI),请根据以下提示在TaurusDB中使用SQL基本操作获取汇报所需的数据!回复带有华为云账号的正确数据截图,第二天上午12点前将会收到抽奖链接进行抽奖!活动时间:即日起-2024.12.30 12:00抽奖礼品奖品名称数量备注开发者装备包31.抽奖链接将于正确回帖后的第二天12点前私信发送2.每个华为云账号仅一次抽奖机会3.回帖格式:数字(可保留两位小数)+带有华为云账号和查询结果的截图4.完成正确回帖方可参与有效抽奖,未完成正确回帖或回帖账号与抽奖账号不一致视为无效抽奖GaussDB定制手机支架20GaussDB定制咖啡杯50华为云资源代金券100回帖示例:ROI:xxx(正确数字)实验准备点击领取华为云云资源代金券(抵扣实验消耗)>>>注册/登录华为云账号并完成实名认证购买华为云数据库TaurusDB进入华为云 官网:cid:link_2购买云数据库TaurusDB资源,提交后,“返回云数据库TaurusDB列表”,等待创建完成,等待过程大概需要十分钟                 购买规格如下: 计费模式:按需付费 区域:华北-北京四 实例类型:集群 可用区类型:默认即可 性能规格:默认即可 CPU架构:x86/鲲鹏;2vCPUs|8GB 管理员密码:自行设置其余各项默认,点击“立即购买”,确认后“提交”​             创建数据库,导入数据表登录数据库实例,创建数据库userdate登录数据库:“登录”->输入密码,测试连接,打开按钮->点击“登录”新建数据库:点击“新建数据库”,输入数据库名称“userdate”,点击“确定”    2. 导入数据脚本userdate.sql:选择“导入”->“新建任务”按照如下参数导入【附件】数据表userdate.sql,点击“创建导入任务”导入类型:sql文件来源:上传文件附件存放位置:点击“创建OBS桶”完成创建选择附件:将文件userdate.sql用鼠标拖至上传区域其余选项默认即可                                  获取关键业务汇报数据返回“SQL查询”页面   2. 计算本次运营活动的ROI,回复带有华为云账号的正确数据截图,第二天上午10点前将会收到抽奖链接进行抽奖!ROI计算方式:回报/投入ROI计算SQL语句提示:select sum(payment_amount)/30000 FROM userdate            删除数据库实例,防止继续扣费            1. 点击“导入·导出”,删除已上传表格            2. 返回“云数据库TaurusDB控制台”,点击“更多”,选择“删除实例云数据库控制台:https://console.huaweicloud.com/gaussdbformysql/?region=cn-north-4&engine=taurus#/gaussdbformysql/management/list3. 进入“OBS桶列表”,选择“删除”注:桶内如果有对象无法进行删除,需点击进入桶,删除里面所有对象后,才能删除桶
  • [技术干货] GaussDB DWS相关组件
     OM:运维管理组件,提供触发式运维管理功能。每个节点都部署。 CM:集群管理组件,提供自动化集群管理功能。每个节点都部署。 GTM:全局事务管理,负责生成和维护全局事务ID、事务快照、时间戳等全局唯一的信息。     DWS集群部署2个,一主一备,分布在不同的节点上。 WLM:工作负载管理,控制系统资源的分配,防止过量业务负载对系统的冲击而导致业务拥塞和系统崩溃。     内置在CN,DN实例内。 CN:协调节点。负责接收来自应用的访问请求,并向客户端返回执行结果;     负责分解任务,并调度任务分片在各DN上并行执行。决定了对外提供的业务访问能力,     默认部署2个,最大支持5个,可以在console上增删CN实例。 DN:数据节点。负责存储业务数据(支持行存、列存、混合存储)、执行数据查询任务以及向CN返回执行结果。     决定了对外提供的业务处理能力,根据节点规格,每个节点部署2-4个,DWS目前最大支持1024个。  
  • [技术干货] GaussDB 企业版的组件-主从模式
    ETCD:分布式键值存储系统(Editable Text Configuration Daemon)。用于共享配置和服务发现(服务注册和查找)。CMS:集群管理模块(Cluster Manager)。管理和监控分布式系统中各个功能单元和物理资源的运行情况,确保整个系统的稳定运行。Data Node:数据节点DN,负责存储业务数据、执行数据查询任务以及返回执行结果。
  • [技术干货] GaussDB 企业版的组件-分布式模式
    Coordinator Node:协调节点CN,负责接收来自应用的访问请求,并向客户端返回执行结果;负责分解任务,并调度任务分片在各DN上并行执行。GTM:全局事务管理器(Global Transaction Manager),负责生成和维护全局事务ID、事务快照、时间戳、Sequence信息等全局唯一的信息。Data Node:数据节点DN,负责存储业务数据、执行数据查询任务以及向CN返回执行结果。
  • [技术干货] GaussDB的驱动
    华为官网上面, 不同部署模式的驱动不相同:开发指南(分布式_8.x)开发指南(主备版_8.x)开发指南(分布式_3.x)开发指南(主备版_3.x)开发指南(分布式_2.x)开发指南(主备版_2.x)https://support.huaweicloud.com/distributed-devg-v3-gaussdb/gaussdb-12-0055.html开发指南页
  • [技术干货] GaussDB的版本
    Gaussdb其实有多种版本.最开始 他支持多种兼容模式, 比如A代表oracle B代表MySQL PG代表PG数据库但是后来华为进行了一些收缩。现在应该是这样的模式:GaussDB 默认是PG模式. 华为云和私有化部署均有.GaussDB for MySQL 是 MySQL模式,也开始多种部署.GaussDB DWS 应该是数据仓库。RDS for mysql,postgresql,sqlserver,Mariadb都是开源数据库. 直接封装提供服务除此之外还有nosql数据库比如RDS for redis,mongodb 等。最后其实还有一个是 openGauss数据库他与GaussDB是不太一样的.不支持分布式, 只支持主从模式。
  • [技术干货] GaussDB相对于PG的增强
    GaussDB与PostgreSQL的关系最早GaussDB内核引擎基于PostgreSQL9.2开源版本不断演进,根据PG-XC架构演生了多CN架构,主要开发了分布式执行框架(stream算子)、向量化引擎等领域中较重要的特性。目前GaussDB除了保留PostgreSQL的标准接口和公共函数外,在自研生态、架构和关键技术上也有了新的发展,开源了集中式部署的能力,重构了存储引擎和优化器。GaussDB与PostgreSQL有如下不同:PostgreSQL是进程模型,而GaussDB是线程池模型。PostgreSQL只支持行存,GaussDB有行存,列存,还有Ustore。PostgreSQL仅有集中式,GaussDB一套内核既支持集中式,又支持分布式。GaussDB有很多独特的特性,比如GTM-Lite、Numa-Aware、两地三中心、同城双集群、动态脱敏、全密态、防篡改。
  • [技术干货] openGauss存储过程创建及应用
    一、引言openGauss 是一款开源关系型数据库管理系统,广泛应用于企业级应用中。随着数据量的增长和业务逻辑的复杂化,数据库管理和操作的自动化需求越来越高。存储过程(Stored Procedures)作为数据库中重要的编程工具,能够极大地简化复杂操作,提高系统的性能和安全性。本文将详细介绍 openGauss 的存储过程,并提供具体的代码和案例,以帮助读者更好地理解和应用这些工具。二、存储过程1. 什么是存储过程存储过程是一组预先编写好的 SQL 语句集合,存储在数据库中,可以通过调用存储过程来执行一系列操作。存储过程能够简化复杂的数据库操作,减少代码重复,提高效率。此外,存储过程运行在数据库服务器端,这意味着可以减少客户端和服务器之间的通信开销,提高执行效率。存储过程的特点包括:封装性:将一系列操作封装在一个过程里,简化调用。重用性:定义一次,可以在多个地方调用,减少代码重复。安全性:通过存储过程可以控制访问权限,提高数据安全性。性能:减少客户端和服务器之间的通信,执行效率高。2. 创建和使用存储过程在 openGauss 中,创建存储过程使用 CREATE PROCEDURE 语句。一个存储过程可以包含多个输入参数、输出参数,甚至没有参数。下面是一个详细的例子,演示如何创建和调用存储过程。创建员工表-- 创建员工表CREATE TABLE employees ( id INT PRIMARY KEY, name VARCHAR(100), salary NUMERIC(15, 2), department VARCHAR(100) );创建存储过程-- 创建插入员工的存储过程CREATE OR REPLACE PROCEDURE add_employee( emp_id INT, emp_name VARCHAR, emp_salary NUMERIC, emp_department VARCHAR )LANGUAGE plpgsql AS $$ BEGIN INSERT INTO employees (id, name, salary, department) VALUES (emp_id, emp_name, emp_salary, emp_department); END; $$;-- 创建更新触发器函数-- 创建更新员工的存储过程CREATE OR REPLACE PROCEDURE update_employee( emp_id INT, emp_name VARCHAR, emp_salary NUMERIC, emp_department VARCHAR ) LANGUAGE plpgsql AS $$ BEGIN UPDATE employees SET name = emp_name, salary = emp_salary, department = emp_department WHERE id = emp_id; END;$$;-- 创建删除员工的存储过程CREATE OR REPLACE PROCEDURE delete_employee(emp_id INT) LANGUAGE plpgsql AS $$ BEGIN DELETE FROM employees WHERE id = emp_id; END;$$;-- 创建查询员工的存储过程CREATE OR REPLACE PROCEDURE get_employee(emp_id INT) LANGUAGE plpgsql AS $$ BEGIN PERFORM * FROM employees WHERE id = emp_id; END; $$;调用存储过程-- 调用存储过程插入员工CALL add_employee(1, 'John Doe', 50000, 'Engineering');-- 调用存储过程更新员工CALL update_employee(1, 'John Doe', 55000, 'Marketing');-- 调用存储过程删除员工CALL delete_employee(1);-- 调用存储过程查询员工CALL get_employee(1);3. 存储过程的高级应用存储过程不仅可以简化常见的增删改查操作,还可以用于更复杂的业务逻辑处理。以下是一些存储过程的高级应用场景:批量数据处理在实际业务中,经常需要对大量数据进行批量处理,如批量插入、批量更新等。使用存储过程可以极大地简化这些操作,并提高执行效率。-- 定义员工记录的复合类型CREATE TYPE emp_record AS ( id INT, name VARCHAR(100), salary NUMERIC(15, 2), department VARCHAR(100) );-- 创建批量插入员工的存储过程CREATE OR REPLACE PROCEDURE batch_insert_employees(emp_records emp_record[]) LANGUAGE plpgsql AS $$ DECLARE rec emp_record; BEGIN FOREACH rec IN ARRAY emp_records LOOP INSERT INTO employees (id, name, salary, department) VALUES (rec.id, rec.name, rec.salary, rec.department); END LOOP; END; $$;-- 调用批量插入存储过程CALL batch_insert_employees(ARRAY[ ROW(2, 'Jane Doe', 60000, 'HR')::emp_record, ROW(3, 'Alice', 70000, 'Finance')::emp_record, ROW(4, 'Bob', 80000, 'IT')::emp_record ]);数据校验和清洗在存储过程中可以添加数据校验和清洗的逻辑,确保插入数据库的数据的完整性和准确性。例如,可以在插入员工数据前,检查数据是否符合业务规则。CREATE OR REPLACE PROCEDURE add_employee_with_validation( emp_id INT, emp_name VARCHAR, emp_salary NUMERIC, emp_department VARCHAR ) LANGUAGE plpgsql AS $$ BEGIN IF emp_salary < 0 THEN RAISE EXCEPTION 'Salary cannot be negative'; END IF; IF emp_department IS NULL THEN RAISE EXCEPTION 'Department cannot be null'; END IF; INSERT INTO employees (id, name, salary, department) VALUES (emp_id, emp_name, emp_salary, emp_department); END; $$;-- 调用存储过程插入员工CALL add_employee_with_validation(5, 'Charlie', 5000, 'Sales');自动化任务存储过程可以用于自动化任务,如定时任务、数据备份等。可以结合数据库调度器(如 cron 表达式)来实现定时调用存储过程,完成自动化管理。-- 定时任务:每天凌晨2点备份员工表CREATE OR REPLACE PROCEDURE backup_employees() LANGUAGE plpgsql AS $$ BEGIN EXECUTE 'COPY employees TO ''/path/to/backup/employees_' || to_char(current_date, 'YYYYMMDD') || '.csv'' WITH CSV HEADER'; END; $$;
  • [技术干货] openGauss 6.0安装过程解除对root用户依赖之gs_preinstall
    在给客户部署业务系统时,由于openGauss数据库的预安装过程需要用到root用户执行,总会被挑战root用户权限太大,若有风险谁负责,只能怯怯的说我们仅安装一个数据库,很快用完了就释放。而openGauss 6.0版本和5.0版本相比,数据库安装流程中的预安装命令(gs_preinstall)以及校验操作系统命令,同时扩容命令可以用非root命令执行了。用非root命令执行预命令,在安全和易用性等方面都有很大的改进(当然还有一些前提条件需要root用户执行,期待后续版本的继续优化),可以减少用户执行过程的用户切换,也可以控制root用户权限控制。一定程度减少了用户误操作对整个系统的影响范围。除了gs_preinstall外,做了类似改进的还有扩容(gs_checkos)和校验(gs_checkos),本文仅介绍gs_preinstall。(其余命令待后文整理)。1.执行前提条件本文由于是单机版安装所以未执行gs_sshexkey -f host,直接执行设置os参数这步,需要注意的是,前提条件的操作,仍然需要以root用户执行。详情参考官网资料,点击文末阅读原文。1.1设置OS参数:注意直接按照官网资料执行会报错Invalid argument,如下:该问题为已知资料问题,执行时需去掉双引号,即可成功。echo 'kernel.sem=250 6400000 1000 25600' >> /etc/sysctl.conf1.2定时任务权限赋予普通用户执行定时任务的权限echo "xxx" >> /etc/cron.allow重启定时任务使生效。systemctl restart crond1.3 修改最大文件描述符2.切换至omm用户,执行preinstall[omm@ecs-oe-2203 script]$ ./gs_preinstall -U omm -G dbgrp -X /opt/software/opengauss/clusterconfig.xml3.source环境变量preinstall成功后,用omm用户执行gs_install,报错:因是环境变量问题,因此回退至root用户,先source环境变量,再执行gs_install命令,就可以成功。[root@ecs-oe-2203 script]# source /home/omm/.bashrc[root@ecs-oe-2203 script]# su omm4.执行gs_install切换至omm用户,继续执行gs_install,安装成功,登录默认数据库并查询。Gs_checkos和gs_expansion的会在后续发出,敬请关注。本文作者本文内容来自于数据库领域资深技术专家赵锋老师,希望我们的文章正好能解决你的问题。
  • [问题求助] TPOPS什么都不显示,是什么问题?
    tpops什么都不显示添加了主机  安装包
  • [问题求助] TPOPS上进行数据库实例备份失败
    TPOPS上新建了一个备份计划,执行到64%后失败了。2024-08-13 20:31:562024-08-13 21:24:20/data/backupNAS全量手动--64%失败页面报错日志如下:[2024-08-13 20:31:59.324]The task is running[2024-08-13 21:24:20.116]{"detailmsg":"Backup retry failed 3 times.Backup failed. [GAUSS-60202]:Result exception error : Roach task is abnormal or roach action is not executed right now still.","retcode":1}[2024-08-13 21:24:20.284]jobPostProcess starting...[2024-08-13 21:24:20.285]queryProcessBackupJob execute failed. Reason: SYS_EXCEPTION:OP_STATUS_FAILURE备份计划配置参数如下-存储方式:NASNAS服务器部署模式:单服务器备份类型:全量备份方式:手动备份存储容量告警阈值(%):80备份根路径 :/data/backup分布式gaussdb库的数据库实例挂载的nas如下:[root@localhost omm]# df -Th Filesystem                          Type      Size  Used Avail Use% Mounted on devtmpfs                            devtmpfs   64G     0   64G   0% /dev tmpfs                               tmpfs      64G  256K   64G   1% /dev/shm tmpfs                               tmpfs      64G  4.1G   60G   7% /run tmpfs                               tmpfs      64G     0   64G   0% /sys/fs/cgroup /dev/mapper/klas-root               xfs       3.0T  486G  2.6T  16% / tmpfs                               tmpfs      64G     0   64G   0% /tmp /dev/mapper/klas-cluster_data_data1 ext4      492G   73M  467G   1% /cluster/data/data1 /dev/mapper/klas-cluster_data_etcd  ext4       63G  428M   59G   1% /cluster/data/etcd /dev/sda2                           xfs       482M  212M  271M  44% /boot /dev/sda1                           vfat      100M  6.4M   94M   7% /boot/efi tmpfs                               tmpfs      13G     0   13G   0% /run/user/1000 tmpfs                               tmpfs      13G     0   13G   0% /run/user/0 tmpfs                               tmpfs      13G     0   13G   0% /run/user/993 tmpfs                               tmpfs      13G     0   13G   0% /run/user/1001 10.56.24.47:/nasDir                 nfs4      1.0T  13G 1021G   2% /data/backup/nas/data 计划开始执行时,一直有写入,查看nas写入大小13G左右后,又回退到初始值了,然后TPOPS页面显示报错了。请专家帮忙看看,分析下原因。
  • GaussDB关键技术原理|高可用:两地三中心跨Region容灾
    接上篇GaussDB关键技术原理|高可用:逻辑复制。从逻辑复制方面对GaussDB的高可用能力进行了介绍,本篇将从两地三中心跨Region容灾方面继续解读GaussDB高可用技术。4 两地三中心跨Region容灾4.1 概述两地三中心,顾名思义,两地指的是两座城市,即同城和异地,三中心指的是生产中心,同城容灾中心以及异地容灾中心。近年来,国内外频繁出现自然灾害,以同城双中心加异地灾备中心的“两地三中心”的灾备模式也随之出现,这一方案兼具高可用性和灾难备份的能力。同城双中心是指在同城或邻近城市建立两个可独立承担关键系统运行的数据中心,双中心具备基本等同的业务处理能力并通过高速链路实时同步数据,日常情况下可同时分担业务及管理系统的运行,并可切换运行;灾难情况下可在基本不丢失数据的情况下进行灾备应急切换,保持业务连续运行。异地灾备中心是指在异地的城市建立一个备份的灾备中心,用于双中心的数据备份,当双中心出现自然灾害等原因而发生故障时,异地灾备中心可以用备份数据进行业务的恢复。数据库实例之间借助存储介质或者不借助存储介质直接实现数据的全量和增量同步。当主数据库实例(即生产数据库实例)出现地域性故障,数据完全无法恢复时,可考虑启用将灾备数据库实例升主,以接管业务。GaussDB当前提供基于流式复制的异地容灾解决方案。目前需要通过om_agent的https REST API来操控数据库实例实现异地容灾。4.2 异地容灾部署示例集中式主集群是同城跨AZ的单集群,5台服务器,4副本,CMS-4副本,ETCD-5副本。Server5可以看做是仲裁副本,为上海2机房脑裂时,提供仲裁能力。分布式:分布式示例主集群是同城跨AZ的单集群,33台服务器,32C32D-4副本,GTM-4副本,CMS-4副本,ETCD-5副本。server33可以看做是仲裁副本,为北京2机房脑裂时,提供仲裁能力。容灾集群为16台服务器,16C32D-2副本,需要开启最大可用模式,1个副本故障时任何对外提供服务,GTM-4副本,CMS-4副本,ETCD-3副本。由于机器数量有限,需要支持单服务器上部署2个主DN的部署方式。特别说明:图中展示的是合肥地域集群为正常集群时的组网,该集群成为灾备集群后,不会再有主DN,变为首备与级联备。4.3 总体设计集中式部署场景:主实例和灾备实例副本数可不同,灾备集群最少为1副本。图 两地三中心异地容灾方案集中式部署场景分布式部署场景:支持灾备集群的CN个数和主集群CN个数不对等。主集群和灾备集群DN分片数要求相同,DN分片内副本数可不同,灾备集群最少为1副本。图 两地三中心异地容灾方案分布式部署场景容灾方案提供如下操作流程:容灾搭建:两个正常集群成为容灾状态下的主集群和灾备集群。图 两地三中心异地容灾方案集中式部署容灾搭建集群变化1. 主备集群副本数可不同。2. 灾备集群有首备+级联备概念,只有首备从主集群主DN拷贝全量数据并建立异地流式复制关系。3. 灾备集群内级联备从首备拷贝数据,并与首备建立流式复制关系。灾备集群升主failover:无论主集群是否异常,灾备集群都可以通过升主成为正常集群对外提供服务,并脱离容灾。演练特性-主备集群switchover:主备集群在都是正常的情况下进行倒换,主集群降为备机,备机升为主机。图 两地三中心异地容灾方案集中式部署failover与switchover集群变化主集群容灾解除:用于在灾备集群升主后,主集群删除容灾信息,脱离容灾。容灾状态查询:容灾状态日常监测,上报集群容灾状态、容灾搭建进度、failover进度、switchover进度,集群RTO,RPO实时数值。上报项含义hadr_cluster_stat (主备集群都可查到)参与容灾的集群状态hadr_establish_stat容灾搭建过程中主备集群搭建进度查询,显示进度百分比。hadr_failover_stat (备集群可查到)灾备集群升主过程进度,hadr_cluster_stat = promote时hadr_failover_stat中的值有效,显示进度百分比。hadr_switchover_stat (主备集群都可查到)计划内switchover过程进度,hadr_cluster_stat = switchover时hadr_switchover_stat中的值有效,显示进度百分比。RTO(主集群可查到)集群容灾RTO(所有分片的最大值)RPO(主集群可查到)集群容灾RPO(所有分片的最大值)容灾状态下支持如下功能:流控:通过GUC参数设置目标值,对主集群的日志产生速度进行控制,以保证RPO,RTO。压缩:主备集群间日志传输可打开压缩,节约带宽,压缩比70%。4.4 容灾搭建容灾搭建总体流程图 流式容灾集群搭建流程图图 灾备集群搭建build备集群实例流程图容灾流程图说明灾备集群搭建主流程:1. 管控A下发搭建新集群A,管控B下发搭建新集群B。2. 管控A,B同时对集群下发灾备集群搭建指令,假设A为主集群,B为灾备集群。B集群中各实例配置A集群中对应节点实例的IP、PORT信息,A集群同样添加B集群中主备的IP、PORT信息。3. 选择B集群中首备实例。向B集群主备实例下发全量重建指令。4. 待B集群主备重建完成,建立A集群和B集群中主备的流复制,并下发B集群重建级联备指令。5. 待B集群所有实例重建成功,且B集群主备实例和A集群对应备机(分布式下对应分片的备机)建立流复制,其他B集群备机(分布式下同分片内)和首备建立连接成功后,返回灾备搭建成功。容灾集群流式日志复制图 流式容灾灾备集群流复制复制消息序列图1. 在开启容灾阶段:在主集群每个副本上,配置replconninfo、hadr_recovery_time_target、hadr_recovery_point_target GUC参数,配置pg_hba.conf;在灾备集群的每个副本上,配置replconninfo参数。2. CM仲裁选举灾备集群中的首备。3. 灾备集群首备轮询主集群中所有的副本,直到找到主DN。4. 灾备首备发起日志复制请求,包括:版本校验、对端状态校验、系统一致性校验、日志一致性校验;灾备首备创建和继续流复制槽,流复制槽名称采用application_name + _hadr方式拼接,以便和主集群同名副本进行区分。5. 主集群主DN遍历所有主集群walsender,获取多数派副本已经同步的日志LSN位置的最小值,并将首备请求LSN位置到该LSN位置之间的日志发送给首备。6. 灾备集群首备接受到日志之后,由walreceiver writer下盘。7. 灾备集群其他副本对首备发起级联复制请求,首备将上述请求LSN位置到本地下盘日志LSN位置之间的日志,级联发送到各个级联副本。8. 级联副本接受到日志之后,将本地的日志下盘位置和日志回放位置反馈给首备。9. 首备将灾备集群中所有副本中日志下盘的多数派LSN位置和日志回放的多数派LSN位置反馈给主集群的主DN。10. 主集群主DN将首备反馈的灾备集群多数派日志下盘位置,作为日志回收以及灾备RPO流控的判断条件(之一)。11. 主集群主DN将首备反馈的灾备集群多数派回放下盘位置,作为灾备RTO流控的判断条件(之一)。容灾集群流式日志复制的高可用主集群少数派副本故障图 主集群发生少数派副本消息序列图1. 主集群CM发起锁分片和重新选主。2. 灾备集群首备的复制链接中断,wal receiver线程退出,重新开始轮询主集群各个副本。3. 主集群新主选主成功。4. 灾备集群轮询到新主,再次开始流式日志复制。5. 由于发送给灾备集群首备的日志都是在主集群已经达成多数派的,因此不会发生日志分叉的问题。灾备集群少数派故障:图 灾备集群发生少数派副本消息序列图1. 灾备首备故障,跨region复制中断。2. 灾备CMS发起首备重新选举,类似主集群选主:首先锁分片,然后从剩余备副本中找到本地日志term最大、日志最大的那个副本,选为首备,最后再给剩余级联备副本下发连接新首备的命名。3. 先首备轮询主集群各个副本,请求跨region日志复制,流程同上。4. 灾备集群中,其他副本在从新首备请求日志复制时,可能会出现本地日志大于新首备的情况(故障再加回场景),由于日志不会发生分叉,因此在这种情况下,该日志较多的级联备只需要在日志一致性校验阶段等待新首备的日志超过本地日志即可。CN支持流复制机制根据上述分布式容灾搭建的对应关系,备集群CN需要和主集群的CN建立一对一的流式容灾关系以保证日志的持续拷贝和回放。该设计的基本思路同集群内的主备关系,但是不要求CN间复制是强同步的,所以修改CN的synchronous_commit = off,不阻塞主集群CN的提交。在备集群的CN和备机一样,以standby模式启动,当本地日志回放结束后0启动walreceiver线程通过解析replconninfo参数建立和主集群CN walsender的连接。由主集群CN walsender开始持续发送xlog日志,再由备集群CN本地回放日志使数据和主集群CN保证一致。故障处理和原集群内主备一致。当备CN未连接主CN时,备CN标记为disconnected状态;当日志crc校验不一致时备集群CN将自己的build reason标记为wal segments removed状态;当主备断连时标记为connecting状态。主要交互流程如图所示。图 灾备集群搭建备集群CN实例build流程图同时对于新增的CN流复制应考虑日志回收的逻辑。日志回收总体方案和原DN主备逻辑一致,先参考本地日志是否大于wal_keep_segments参数,若大于则主集群CN参考对应流复制槽,(目前只有备CN的槽位)日志落盘位置,保证正向场景下备CN所需日志不会被主CN回收。考虑到异常的备CN断连场景,主CN的日志回收应参考最大日志保留量max_size_for_xlog_prune参数,保证在不影响主集群CN可用性下,为备CN保留最多的日志,减少全量build的可能。灾备集群的CN个数和主集群CN个数不对等场景下建立容灾关系图中主备集群CN对应关系的处理说明:受限于replconninfo配置个数的上限,集群达到一定规模后不可能将对端所有的节点链接信息都配上,所以OM在主备集群搭建容灾关系时CN依据如下计算方式进行对应。当前使用CN instance id从小到大排序后的normal CN id list进行主备集群CN配对,比如主集群有M个normal CN,灾备集群有N的normal CN,对M,N中较小的值取模对应。可能出现的情况分析如下:图  主集群CN多于灾备集群CN容灾搭建示例(1)、如果主集群的CN多(上图M=5),灾备集群的CN少(上图N=3),以灾备集群的CN数量为准, 一对一进行build之后建立replication;主集群多出来的CN没有灾备CN对应,配置有容灾信息replconninfo,但不发生作用。灾备集群的CN会配置多条容灾使用的replconninfo,比如主集群的CN1挂了,灾备CN1可以连到CN4上触发build。图 主集群CN少于灾备集群CN容灾搭建示例(2)、如果灾备集群的CN多(上图N=5),主集群的CN少(上图M=3)(主要出现场景为计划内switchover、灾备集群升主后反向搭建容灾关系),此时灾备集群会有多个灾备CN同时和主集群相同CN建立流式复制的关系,比如上图上CN1和CN4都是与主集群的CN1建立容灾关系。容灾过程中灾备故障CN的处理1. 主集群CN故障导致灾备CN故障的处理机制主集群处于容灾的CN发生剔除,或者主备集群间网络断链导致灾备CN处于故障状态,CN采用Need_repair(<build_reason>)上报机制,灾备CM对这一状态的CN不做剔除处理。主集群处于容灾的CN发生剔除或者网络断链状态,灾备集群对应的CN感知到断连,将上报Need_repair(Disconnected)状态,并由CM显示。主集群CN因为修复等操作发生build,灾备CN试图同步的日志和本地xlog日志不一致,灾备CN需要上报Need_repair(wal segment removed)等状态,灾备CMS感知后,会通知CN所在CMA下发CN全量build(从主集群对应cn build,build完成后自动拉起),build完成后CN恢复Normal状态。相关命令gs_ctl build -b cross_cluster_full -Z coordinator -D <dir_path> -M standby。灾备CN build期间,显示building状态,不参与barrier推进,也不参与备机只读的接入。灾备集群的CN会将当前连接成功的生产集群CN的序号持久化到文件里边,重启后会从文件读取最近一次的CN序号,优先连接最近一次连接的成功的对端CN。在尝试连接失败次数达到一个阈值(当前阈值设定为3000次)时候,才会尝试连接下一个replication info里边的CN。2. 灾备集群CN故障的处理机制灾备的CN故障同主集群有所不同:灾备集群的CN是按standby起的,不会和其他CN/DN联系,满足条件(CN心跳超时25s、CN反复重启)会被剔除,置Deleted状态。Deleted状态的CN不参与barrier推进,也不参与备机只读的接入。被剔除CN由CMA检测满足自动加回条件后进行自动修复,或手动进行CN修复。修复期间会触发全量build。修复完成后CN恢复Normal状态。要保证最后一个非超前状态的CN不触发build,否则会出现容灾集群无CN可用的暂态。3. 灾备集群CN故障的告警在容灾状态下,灾备集群CN如果出现Need_repair(Disconnected),上报容灾实例断连告警,并在Detail信息中体现本端实例id与对端实例id的容灾关联性。该告警信息上报管控。详见《3.3.8系统外部接口(和其他产品)》4. 灾备集群CN状态转化汇总图 灾备集群CN状态转换约束对应集群只要有一个CN还活着,就能提供服务:容灾状态的集群同样保证最后一个CN不做剔除。灾备集群需要始终保持至少一个CN不处于waiting或者deleted状态。异地容灾集群间日志传输需要支持日志压缩受客户场景跨集群间的网络带宽限制,将跨集群的xlog日志在发送端压缩,接收端解压,以提高传输效率。1. 功能实现:添加控制xlog压缩启停的guc参数enable_wal_shipping_compression,描述如下:enable_wal_shipping_compression参数说明:在流式容灾模式下设置启动跨集群日志压缩功能。该参数属于SIGHUP类型参数。取值范围:布尔型该参数仅作用于跨集群传输的一对walsender与walreceiver中,作用于主集群DN。默认值:false添加日志类型type ’C’用于表示被压缩的wal类型,在处理前会执行解压操作。采用了已在Gauss库中的lz4无损压缩算法进行日志压缩,使用默认压缩级别LZ4_compress_default(),具体实现如下:日志发送方的Walsender.cpp:XLogSendPhysical()中,在XLogRead()函数将数据传入t_thrd.walsender_cxt.output_xlog_message前先进行压缩,并更改类型表示为’C’,之后将压缩后的数据传入output_xlog_message,同时更改pq_putmessage_noblock中数据长度为压缩后的大小。日志接收方的walreceiver.cpp:XLogWalRcvProcessMsg()中,type=’C’时,将buf中的数据先进行解压,用解压后的decompressBuf继续之后的逻辑。为了减少cpu在压缩/解压上的性能损失,仅对异地容灾的流式复制开启压缩功能,集群内的流式复制不开启压缩功能。2. 压缩率在流式容灾集中式场景开发环境自测中,使用8核虚拟机tpcc 50仓 64并发进行tpcc测试,带宽充足场景下,tpcc执行中测得xlog压缩率平均在64.8%左右。异地容灾的流控机制流式容灾在集中式场景已经添加了流控参数,描述如下:hadr_recovery_time_target参数说明:在流式容灾模式下设置hadr_recovery_time_target能够让备集群完成日志写入和回放。该参数属于SIGHUP类型参数。取值范围:整型,0~3600 (秒)0是指不开启日志流控,1~3600是指备机能够在hadr_recovery_time_target时间内完成日志的写入和回放,可以保证主集群与备集群切换时能够在hadr_recovery_time_target秒完成日志写入和回放,保证备集群能够快速升主。hadr_recovery_time_target设置时间过小会影响主机的性能,设置过大会失去流控效果。默认值:0hadr_recovery_point_target参数说明:在流式容灾模式下设置hadr_recovery_point_target能够让备集群完成日志刷盘的rpo时间。该参数属于SIGHUP类型参数。取值范围:整型,0~3600 (秒)0是指不开启日志流控,1~3600是指备机能够在hadr_recovery_point_target时间内完成日志的刷盘,可以保证主集群与备集群切换时日志差距能够在hadr_recovery_point_target秒内,保障备集群升主日志量。hadr_recovery_point_target设置时间过小会影响主机的性能,设置过大会失去流控效果。默认值:0这两个参数在客户对于异地容灾RPO,RTO有强烈需求的情况下,可以进行配置用于保证在任何时刻RPO,RTO都能达到客户要求。在分布式部署场景下,打开流控,流控机制会在分片级别上生效。比如RPO目标是10s,hadr_recovery_point_target可配置为10s,超过这个值的时候,流控生效,会对主集群日志写入速率进行反压,降低业务性能来保证RPO达标。比如RTO目标是10min,hadr_recovery_time_target可以配置60s,超过这个值的时候,流控生效,会对日志写入速率进行反压,降低业务性能来保证RTO达标。这里hadr_recovery_time_target控制灾备升主期间日志回放的耗时,是整个灾备集群升主流程耗时的一部分。针对异地容灾的RPO需求,新增了RPO流控与原有的RTO流控共同作用,对应修改了系统视图global_streaming_hadr_rto_and_rpo_stat与gs_hadr_local_rto_and_rpo_stat中的current_sleep_time列为rto_sleep_time和rpo_sleep_time。global_streaming_hadr_rto_and_rpo_stat参数说明:参数类型描述hadr_sender_node_nametext节点的名称,包含主集群和备集群首备。hadr_receiver_node_nametext备集群首备名称。current_rtoint流控的信息,当前主备集群的日志rto时间(单位:秒)。target_rtoint流控的信息,目标主备集群间的rto时间(单位:秒)。current_rpoint流控的信息,当前主备集群的日志rpo时间(单位:秒)。target_rpoint流控的信息,目标主备集群间的rpo时间(单位:秒)。rto_sleep_timeintRTO流控信息,为了达到target_rto这一预期,主机日志发送所需要的睡眠时间(单位:微秒)rpo_sleep_timeintRPO流控信息,为了达到target_rpo这一预期,主机日志生成所需要的睡眠时间(单位:微秒)gs_hadr_local_rto_and_rpo_stat参数说明:参数类型描述hadr_sender_node_nametext节点的名称,包含主集群和备集群首备。hadr_receiver_node_nametext备集群首备名称。source_iptext主集群主DN IP地址。source_portint主集群主DN通信端口。dest_iptext备集群首备DN IP地址。dest_portint备集群首备DN通信端口。current_rtoint流控的信息,当前主备集群的日志rto时间(单位:秒)。target_rtoint流控的信息,目标主备集群间的rto时间(单位:秒)。current_rpoint流控的信息,当前主备集群的日志rpo时间(单位:秒)。target_rpoint流控的信息,目标主备集群间的rpo时间(单位:秒)。rto_sleep_timeintRTO流控信息,为了达到target_rto这一预期,主机日志发送所需要的睡眠时间(单位:微秒)rpo_sleep_timeintRPO流控信息,为了达到target_rpo这一预期,主机日志生成所需要的睡眠时间(单位:微秒)集中式场景流控逻辑rto计算逻辑是:通过备机每次返回的最新落盘、回放lsn,计算备机日志落盘和回放的速度,估算当前备机所有已接收日志全部完成落盘、回放需要的时间,作为RTO。rpo计算逻辑是:通过主机新生成日志的速度,结合主备落盘日志量差值,估算当前主备日志差相当于主机多少秒的新增,作为RPO。分布式场景流控逻辑在分布式流式容灾中,为了保证分布式一致性采用全局一致性打点,对备机回放做了限制,即每个节点回放到全局targetBarrier点后会停止回放,等待下一个targetBarrier更新。而灾备集群升主时,targetBarrier后的日志会被丢弃,因此不能与普通集群一样按flush点计算RTO/RPORTO新增逻辑是:在集中式逻辑的基础上,因为灾备集群升主时,targetBarrier后的日志会被丢弃,所以当节点日志回放到targetBarrier后即可视为回放完成,RTO=0。灾备集群各节点会将当前是否回放到targetBarrier点,返回给对应的主集群节点,标记此时rto=0。RPO计算逻辑是:由于targetBarrier后的日志灾备升主时会被丢弃,所以应该以备机targetBarrier点与主机最新日志计算RPO。barrierId的最后13位为其生成时的时间信息,RPO算法利用这个时间戳,由灾备返回targetBarrierID,与主机最新生成的currentBarrierID比较,时间差即是灾备升主时丢失日志的时间长度。周期性全局一致性打点与推进图 barrier处理消息序列图消息序列图说明如上图所示是一个barrier点从生成到删除的整个过程,大致可以分为四个部分:barrier生成、barrier解析存储、barrier推进、barrier删除。其中barrier推进是最重要的一环,有它来确定各备节点恢复的位置来达到一致性要求。详细设计Barrier生成Barrier生成是Barrier一致性的前提。Barrier点任一CN都可以发起,但由第一个CN负责生成。若发起barrier生成的CN不是第一个CN,则通知第一个CN进行生成。生成后CN与DN将其落到xlog日志中。负责打点的CN会启动barrier_crearor线程从GTM获取CSN,来生成barrier,格式如下:生成的CSN类型barrier信息格式为 ”csn_%021lu_%013ld”,头部信息固定为csn_,中间21位为得到的csn号,最后13位为时间信息,当前仅用于RPO计算。Barrier解析存储Barrier解析存储是Barrier一致性的基础,备集群上对应的备节点通过walreciever收到xlog日志后,将日志落盘。通过新添加barrier解析线程对新落盘的日志进行预解析,并将解析到的barrier存储在hash table中,并保存当前收到的最大barrier。Hash table在创建日志解析线程前进行创建,在集群卸载时进行释放。Hash table中储存着解析出来的barrier,这些barrier将在回放xlog日志时进行删除。Barrier推进Barrier解析存储是Barrier一致性的关键,这部分稍微复杂一些,需要CN、DN、CMA、CMS、ETCD相互配合进行。barrier一致性点的推进需要五步:CMA通过sql函数查询CN、DN的barrier最大值上报至CMS。此处的barrier为预解析结果,日志实际还未回放;CMS通过收齐各个实例上报的barrier,将其中的最小值作为query barrier;CMA从CMS获取到query barrier,调用sql函数对CN、DN进行查询,确认是否存在该barrier点,将结果上报给CMS。CMS收齐后判断,若该query barrier已达到多数派条件,则作为target barrier点,否则舍弃;CMA读取CMS里存放的target barrier,更新CMA本地的target barrier;CMA通过sql函数设置CN,DN实例的recovery barrier设置为targer barrier。在一次上报中,CMA需要查询执行barrier最大值的上报、本地查询querybarrier是否存在,更新targetbarrier这三步;CMS需要执行querybarrier的更新和targetbarrier的更新。其他说明:Querybarrier达到多数派成为target barrier的条件。单一DN分片内多数派已上报该barrier。所有DN分片都已上报该barrier。CN多数派已经上报该barrier。CN多数派数目动态调整策略:由于主集群允许cn剔除到只有一个cn,所以在故障场景下cn多数派的数目要随时调整,策略为:CN多数派初始值为n_cn=init_cn_number/2 +1。当发现barrier在1分钟内因为达不成cn多数派无法推进,n_cn--;极限值n_cn>=1。当发现barrier可以有大于 n_cn个数的cn参与推进barrier,n_cn++;极限值n_cn<=init_cn_number/2 +1。灾备集群CN不同状态参与barrier推进的情况容灾过程中灾备集群中被Deleted,building的CN对CM的barrier查询请求不会有响应。由于灾备集群CN发生build导致barrier超前推进,它处于等待其他CN的waiting状态,或者容灾过程中灾备集群中处于need repair态的CN是有可能查到CM请求的barrier的,会参与barrier推进。灾备集群CN处于waiting状态的条件改造基于OBS异地容灾方案中增加的sql函数gs_get_local_barrier_status()查询得到当前CN实例redo的barrier。CM通过该函数获得CN实例当前redo的localbarrier,与targetbarrier进行比较,localbarrier>targetbarrier时,该CN置为waiting状态。该状态与CN其他状态的转化参见《3.3.6.3容灾过程中灾备故障CN的处理》。Barrier删除Barrier删除是barrier一致性的终点,Barrier删除发生在xlog日志回放中,在日志回放时,回放到barrier会对回放位置recoverybarrier进行更新,并在hash table将该barrier点删除,完成barrier从生成到删除的全过程。
  • [技术干货] GaussDB关键技术原理:高弹性(一)
    GaussDB关键技术原理:高可用篇,从GaussDB数据库DCF、双集群容灾、逻辑复制及两地三中心跨Region容灾方面对GaussDB高可用能力进行了解读。本篇将分享GaussDB高弹性方面的相关知识,从CBI索引方面对hashbucket展开介绍。1 前言  GaussDB支持hash分布表,hash分布表的数据行根据hash分布列进行hash计算,计算出的hash值被打散到各个DN。随着业务增长数据规模变大,DN的承载能力会逐渐不够,这样就需要对DN节点数量进行扩充。节点数量扩充后,存储于原DN节点的数据就需要进行数据重新分布。目前GaussDB采用的是share-nothing的本地盘架构,各个DN节点独立维护各自的数据,这种架构下数据重分布的难度很大。如下图所示,在线扩容从时间轴上看主要由两部分组成:图1  在线扩容示意图集群加节点阶段:对新加入的DN节点进行元信息的同步,然后更新集群拓扑,启动新节点。设置包含新节点的Installation NodeGroup信息,将老集群的NodeGroup设置为待重分布的状态。数据重分布阶段:对分布在老集群的用户表通过数据重分布搬迁至新集群,在新加节点完成业务上线。数据重分布主要有两种方式,一种逻辑搬迁方式,主要通过SQL接口进行,另一种是物理搬迁的方式,直接通过文件拷贝和日志多流追增进行。本节主要介绍逻辑数据重分布的过程。    由此可见,在线数据重分布是在线扩容的关键步骤。目前已经支持了以表为粒度的逻辑数据重分布,其核心思想是采用SQL接口将原表的数据导入到一个按照新分布方式存储的新表上,然后进行两个表的元数据切换。处理在线业务的核心思想是:将DML操作的UPDATE拆分成INSERT和DELETE,所有INSERT都采用追增写入的模式,写入原表的尾部,通过CTID确定每轮处理数据的范围,使用“{节点ID}+{元组ID}”表示删除的元组位置,原表的数据直接删除,新表的数据追增删除,直至原表和新表数据收敛追平,详细步骤如下图。图2  重分布过程中在线业务处理过程P1:将原表设置为追增模式,创建新表(新增两列表示元组ID和节点ID)、delete_delta表记录删除原组的位置信息,并将新表索引失效,提升基线数据批量插入的效率。P2_1:采用“insert into 新表select * from 原表”的方式完成基线数据的插入。此时用户业务采用追加写的方式写在原表的后面,删除的数据直接进行删除并且将原组ID和节点ID记录在delete_delta表中。P2_2:重建新表的索引,此阶段引入了并行建索引来提升重建索引的效率。P3:采用多轮追增(推进CTID、DELETE、INSERT)的方式完成新表和元数据的数据追平。    P4:拿原表的8级锁,完成元数据切换,保留原表的元信息和新表的数据文件信息。逻辑数据重分布的方式比较类似于VACUUM FULL的运行机制,存在很多约束和限制。首先新老表同时存在,会占用双份磁盘空间影响磁盘的利用率。其次,如果要支持在线的数据重分布,采用SQL接口的方式挑战会比较大,例如表锁冲突,shared-buffer资源争抢等问题。如果两个具有相同分布规则的表需要进行JOIN操作,重分布期间可能存在一个表完成数据重分布,另一个表没有完成,这个阶段两个表就可能存在跨节点的分布式JOIN,与原有的本地JOIN相比性能会下降十分严重。为了解决逻辑扩容在有复杂业务查询场景在线业务的性能劣化问题,我们引入了基于hashbucket表的物理在线扩容方案,不仅可以很好地解决带有JOIN关系业务性能下降的问题,还可以解除预留磁盘空间的约束,同时引入物理扩容的概念,大大提升了在线扩容本身的性能。2 hashbucket介绍  2.1简介  hashbucket表在DN上的数据按照hash值进行聚簇存储,具有相同hash值的数据会统一管理在一个bucket中。从分布式集群的角度看,hashbucket表将用户表拆分为多个分片的形式存储——每个表切分为N个分片,每个DN存储N/DNnum个分片。拆分使用的规则与hash分布规则一致,使用相同的分布列计算hash值。图3显示的是插入一行数据,在CN上根据分布列计算hash值并取模bucket桶长度BUCKETLEN(图中是6)计算出具体的DN节点,在DN节点上对不同的hash值再进行分片拆分。    图3  hashbucket表插入数据逻辑示意图存储的组织方式如下图4所示,假设用户表是hash分布表,在CN上有6个hash bucket桶,其中1~3对应DN1的数据分片,4~6对应DN2的数据分片。CN上存储一个映射关系表示每个DN分片上有哪些bucket桶,用户存入一条数据时将根据分布列的值计算属于哪个bucket桶,再根据CN上的映射关系路由到对应DN分片进行数据存储。图4  存储组织方式示意图如果每张hash分布的表都进行文件拆分,将会导致小文件非常多,给文件系统造成比较大的压力,因此hashbucket采用段页式的存储方式,即所有表都采用一组文件进行存储,后续段页式章节会进行详细介绍。从DN存储节点的角度上看,hashbucket表和普通页式表主要区别在于数据文件管理,事务管理和元数据管理三个方面:    图5  数据管理示意图数据文件: 按照bucket对段页式文件组进行库级别分片存储。事务管理: 按照bucket对CLOG进行实例级分片存储。后文会做详细介绍。元数据管理: pg_class增加库级分片标识、pg_hashbucket增加库级别分片信息。为了能够在CN和DN区分hashbucket表,在pg_class系统表中增加一列relbucket,CN上存储1,DN上存储3,表示将进行分片存储。另外新增一个库级系统表pg_hashbucket,存储hashbucket相关的信息,定义如下表1所示。表1  系统表pg_hashbucket 属性名数据类型注释bucketidoidCN上为PG_HASHBUCKET系统表所在DATABASE绑定的NodeGroup的OID。DN上此列为空。bucketcntintergerCN上不使用此参数,DN上为当前DN所拥有的bucket数量。bucketvectoroidvector_extendCN上不使用此参数,DN上为当前DN所拥有的bucket列表。bucketmaptext用来存储逻辑bucket到物理bucket的映射关系,即16384到1024的映射关系。bucketversionoidvector_extend记录后续hashbucket扩容过程中发生改变的信息版本号。bucketcsntexthashbucket重分布前源节点每个bucket对应的最大CSN,用于新节点可见性判断。bucketxidtexthashbucket扩容,新节点上线设置的next_xid,用于校验是否在阈值范围内。因此,创建库的时候会生成pg_hashbucket中bucket分片的分布信息,hashbucket表拥有库级的特点,即一个库的所有hashbucket表一定具有相同的分布方式。所有hash分布的用户表都可以采用hashbucket分片存储的方式,用户在创建表时通过指定参数来实现,如下:    CREATE TABLE t1 (a int, b text) WITH (hashbucket=on);hashbucket表在扩容的时候通过物理文件搬迁完成,因此每个库以bucket文件为粒度在新节点上线业务,同时原子性地刷新pg_hashbucket系统表。业务会在DN上访问pg_hashbucket系统表过滤bucket list来找到正确的数据。由于hashbucket表对数据文件进行了切片,如果直接创建BTree索引,索引也需要进行切片才能访问到正确的数据,如果计划可以直接剪枝则性能不受影响,如果计划不能剪枝则需要遍历1024/DN分片数棵BTree树,会严重影响性能,因此引入一种新的索引——CBI索引,跨bucket索引,所有bucket一棵BTree,索引中增加bucketid信息,来提升性能,下一章节将会详细介绍。2.2 CBI索引  GaussDB针对hashbucket表有两种索引,bucket全局索引(跨bucket索引,cross-bucket index,CBI)和bucket本地索引(local-bucket index,LBI)。跨bucket索引为hashbucket聚簇存储提供一种跨bucket的索引能力,即在创建索引时,一个索引文件可以对应表级或分区级的所有bucket文件。该索引可以为指定粒度的表提供跨bucket的索引扫描,避免顺序扫描当前表下的大量bucket文件才能查到目标元组,提升查询性能。通过在创建索引时指定“crossbucket=on”可以创建跨bucket索引。图6  创建CBI索引示意图hashbucket表跨bucket索引如下图7所示,只有一个跨bucket索引文件,在扫描该索引时能获取目标元组完备的位置信息(元组所在bucket分片等),读取指定的bucket分片就能获取目标元组。图7  CBI索引结构示意图需要注意的是,在当前版本中跨bucket索引只面向分布式GaussDB,CBI创建的前提是hashbucket聚簇存储开启,仅支持BTree索引,不支持部分索引以及其他类型索引,GLOBAL和LOCAL索引不允许建在同一列,仅支持行存表,GLOBAL CROSSBUCKET索引支持最大列数为30;LOCAL CROSSBUCKET索引支持最大列数为31。2.2.1 CBI索引元组索引元组是一种用于建立索引的数据结构,CBI索引元组的结构如下图所示,包含索引键值、bucket分片id、数据元组信息。当需要访问数据时,通过bucketid找到数据元组所在的bucket分片,然后按数据行id找到对应的数据元组。图8  CBI索引元组结构2.2.2 CBI索引的实现CBI索引创建跨bucket索引创建流程如下:解析SQL语句确定要创建的索引是CBI,进入创建索引流程;创建跨bucket索引关系,进入索引构建流程;索引构建流程中判断索引为跨bucket索引时,遍历每个bucket扫描堆表查找要加到索引中的元组,进入BTree构建流程;BTree构建流程中使用堆表关系和索引关系创建BTree索引,保存扫描到的数据元组数和创建的索引元组数。CBI索引扫描基本思路是,对父表构建索引,索引元组记录所在分片的bucketid,这两个属性作为INCLUDE参数被加入到索引列,封装进索引元组。索引扫描时,先通过BTree遍历找到满足索引键条件的索引元组,然后读取该元组中记录的bucketid,获取目标元组所在的分区和bucket分片,再根据这些信息缩小查找范围获取最终的目标元组。CBI索引插入删除分布式全局索引插入流程与普通索引插入流程基本一致,需要注意的是唯一性检测流程的适配。当插入的数据不允许重复,会触发唯一性检测,也就需要将当前即将插入的数据与已存在数据进行比较,这就需要对特定范围的数据进行扫描。对于跨Bucket索引,这个特定范围需要根据当前索引元组中存储的bucketid来锁定,实现载入相应的目标表。CBI索引清理索引清理对于hashbucket表的处理是通过遍历数据表以及对应的索引分片,分别清理各个分片。引入CBI后检查数据表相关的索引是否为CBI,同时收集当前bucket的bucketid和bucket中dead的数据元组进入BTree清理页面流程。在BTree清理页面流程中,如果索引为CBI,则从索引元组中获取目标元组所在的bucketid,清理目标元组对应的索引元组。    2.2.3 CBI元数据跨bucket索引的元数据可通过系统视图pg_indexes、系统表pg_class查看。系统视图pg_indexes提供对数据库中每个索引的有用信息的访问,包含的关键字段如下表2所示。表2  系统视图pg_indexes部分字段名称类型描述tablenamename索引所服务的表的名称。indexnamename索引名称。tablespacename包含索引的表空间名称。indexdeftext索引定义。系统表pg_class存储数据库对象及其之间的关系。与CBI索引相关的字段如下表3,可以查到跨bucket索引的表空间、访问方法等信息。表3  系统表pg_class部分字段名称类型描述relnamename包含这个关系的名称空间的oidreloptionstext[]表或索引的访问方法,使用"keyword=value"格式的字符串。relbucketOid当前表是否包含hashbucket分片。有效的oid指向 pg_hashbucket表中记录的具体分片信息。NULL表示不包含hash bucket分片。以上内容从CBI索引方面对hashbucket进行了解读,下篇将从优化器剪枝、执行器方面继续介绍GaussDB高弹性技术,敬请期待!
总条数:1666 到第
上滑加载中