-
三头六臂战力增倍--OpenGauss5.0.0一主两备扩容至一主三备OpenGauss支持集群的扩容和缩容,下面简单记录了OpenGauss5.0.0一主两备扩容至一主三备的过程,供各位方家参考指正。检查升级前一主两备集群状态:检查OS状态root用户执行 ./gs_checkos -i A检查结果:没有异常(Abnormal numbers:0),有4个告警,可忽略。建立互信,先增加hostfile192.168.0.222192.168.0.92192.168.0.197192.168.0.53在要加入集群的新机器上创建omm用户和用户组dbgrp,注意omm用户的密码需和其他机器相同。用到linux的Useradd/groupadd/passwd等命令,不做赘述。执行gs_sshexkey命令(注意root 和 omm都要执行)./script/gs_sshexkey -f xmlfile/hostfileroot用户:omm用户:Source环境变量:source /home/omm/.bashrc修改xml文件,增加待扩容加入集群机器的信息:和一主两备部署相类似,请参考:root用户在主机执行扩容命令./gs_expansion -U omm -G dbgrp -X ../xmlfile/cluster_config.xml -h 192.168.0.53命令执行成功,检查集群状态:至此,扩容过程已经完成。业务峰值的时候扩容,过峰之后自然会有扩容的诉求,关于缩容过程的介绍,将在下期进行,敬请关注。
-
MOT在高性能(查询和事务延迟)、高可扩展性(吞吐量和并发量)甚至在某些情况下成本(高资源利用率)这些方面拥有显著优势。低延迟(Low Latency):提供快速的查询和事务响应时间。高吞吐量(High Throughput):支持峰值和持续高用户并发。高资源利用率(High Resource Utilization):充分利用硬件。使用了MOT的应用程序可以达到2.5到4倍的吞吐量。例如,在基于Arm/鲲鹏的华为TaiShan服务器和基于英特尔至强的戴尔x86服务器上,执行TPC-C基准测试(交互事务和同步日志)。MOT提供的吞吐率增益在2路服务器上达到2.5倍,4路服务器上达到3.7倍,在4路256核Arm服务器上达到480万tpmC。在TPC-C基准测试中可观察到,MOT提供更低的延迟将事务速度降低3至5.5倍。在TPC-C基准测试中可观察到,MOT提供更低的延迟将事务速度降低3至5.5倍。此外,高负载和高争用的情况是所有领先的行业数据库都会遇到的公认问题,而MOT能够在这种情况下极高地利用服务器资源。使用MOT后,4路服务器的资源利用率达到99%,远远领先其他行业数据库。这种能力在现代的多核服务器上尤为明显和重要。
-
主备机可获得性本特性自openGauss 1.0.0 版本开始支持DN主备。特性简介为了保证故障的可恢复,需要将数据写多份,设置主备多个副本,通过日志进行数据同步,可以实现节点故障、停止后重启等情况下,openGauss能够保证故障之前的数据无丢失,满足ACID特性。客户价值主备机功能可以支持主机故障时切换到备机,数据不丢失,业务可以快速恢复。特性描述主备环境支持一主多备模式。在一主多备模式下,所有的备机都需要重做日志,都可以升主。一主多备提供更高的容灾能力,更加适合于大批量事务处理的OLTP系统。主备之间可以通过switchover进行角色切换,主机故障后可以通过failover对备机进行升主。初始化安装或者备份恢复等场景中,需要根据主机重建备机的数据,此时需要build功能,将主机的数据和WAL日志发送到备机。主机故障后重新以备机的角色加入时,也需要build功能将其数据和日志与新主拉齐。另外,在在线扩容的场景中,需要通过build来同步元数据到新节点上的实例。Build包含全量build和增量build,全量build要全部依赖主机数据进行重建,拷贝的数据量比较大,耗时比较长,而增量build只拷贝差异文件,拷贝的数据量比较小,耗时比较短。一般情况下,优先选择增量build来进行故障恢复,如果增量build失败,再继续执行全量build,直至故障恢复。为了实现所有实例的高可用容灾能力,除了以上对DN设置主备多个副本,openGauss还提供了其他一些主备容灾能力,比如CM Server(一主多备)以及ETCD(一主多备)等,使得实例故障后可以尽可能快地恢复,不中断业务,将因为硬件、软件和人为造成的故障对业务的影响降到最低,以保证业务的连续性。
-
在一个固定的时间点活间隔一段时间需要频繁触发某一动作,为了使用便捷,有了定时任务,极大的减少了工作的重复性,提高了效率。定时任务的内容 基于定时任务产生的背景,定时任务内容包括:定时任务的创建、任务到达时间点自动执行、删除任务、任务内容的修改(任务 id、任务的关闭开启、任务的触发时间、触发时间间隔、任务内容等)。定时任务 1.创建表 CREATE TABLE tb_test(insert_date timestamp default null,id int default null);显示信息CREATE TABLE创建表成功2.创建定时任务 定时内容为:每间隔一分钟执行一次向表 tb_test 中插入(当前系统时间,1)SELECT pkg_service.job_submit(1,'insert into tb_test values(sysdate,1);',sysdate,'''1min''::interval'); 显示信息 job_submit1 (1 row) 创建定时任务成功 间隔三分钟,查看表中信息 SELECT * FROM tb_test; 显示信息 insert_date | id 2022-09-02 17:50:04 | 1 2022-09-02 17:51: 04 | 1 2022-09-02 17:52:04 | 1 (3 rows)定时任务执行成功3.定时任务停止SELECT pkg_service.job_finish(1,true); 显示信息 job_finish(1 row) 定时任务停止4.定时任务启动SELECT pkg_service.job_finish(1,false); 显示信息 job_finish(1 row) 定时任务启动5.删除定时任务SELECT pkg_service.job_cancel(1); 显示信息 job_cancel(1 row) 删除定时任务
-
最近学习一项新技能opengauss的编译安装,使用安装包安装opengauss之后,xml类型不具备写入,因为默认xml特性未开启,需在./configure编译安装时指定参数 --with-libxml,下面将介绍到opengauss3.0的手动编译安装。openGauss=# CREATE TABLE xmltest ( openGauss(# id int, openGauss(# data xml openGauss(# ); CREATE TABLE openGauss=# INSERT INTO xmltest VALUES (1, '<value>one</value>'); ERROR: unsupported XML feature LINE 1: INSERT INTO xmltest VALUES (1, '<value>one</value>'); ^安装环境虚拟机VM15 操作系统centos7.6 x86架构硬件配置 CPU:1C 内存:2G 磁盘: 60G依赖要求 libaio-devel-0.3.109-13 gcc-c+±4.8.5-44 bison-3.0.4-2 flex-2.5.37-6 bison-3.0.4-2 ncurses-devel-5.9-14.20130511 glibc-devel-2.17-325 patch-2.7.1-12 redhat-lsb-core-4.1-27 readline-devel-6.2-11 perl-5.16.3-299依赖安装 yum install unzip gcc-c++ readline readline-devel libaio-devel flex bison ncurses-devel glibc-devel patch expect源码包及开源第三方软件下载地址: opengauss-sever:cid:link_1 ##由于开源软件编译构建耗时长,特地使用openGauss-third_party编译构建出了一份binarylibs并压缩上传到了网上,用户可以直接下载获取。 已编译好的开源第三方软件:cid:link_0 tar -zxvf opengauss-openGauss-server-v3.0.0.tar.gz tar -zxvf openGauss-third_party_binarylibs.tar.gz ##重命名开源第三方软件解压目录为binarylibs mv openGauss-third_party_binarylibs binarylibs手动编译1. 检查系统版本进入到软件代码目录,执行脚本获取自己系统的版本。cd openGauss-server-3.0.0 sh src/get_PlatForm_str.sh说明:显示的结果表示openGauss当前支持的操作系统,openGauss支持的操作系统为centos7.6_x86_64、openeuler_aarch64、openeuler_x86_64。如果结果显示为Failed或者其他版本,表示openGauss不支持当前操作系统。2. 配置环境变量环境变量配置,根据自己的代码下载位置补充两处“”,将获取到的结果替换下面的***。export CODE_BASE=________ # openGauss-server-3.0.0的路径 export BINARYLIBS=________ # binarylibs的路径 export GAUSSHOME=$CODE_BASE/dest/ export GCC_PATH=$BINARYLIBS/buildtools/***/gcc7.3/ # 是脚本获取出来的系统版本,此处为centos7.6_x86_64 export CC=$GCC_PATH/gcc/bin/gcc export CXX=$GCC_PATH/gcc/bin/g++ export LD_LIBRARY_PATH=$GAUSSHOME/lib:$GCC_PATH/gcc/lib64:$GCC_PATH/isl/lib:$GCC_PATH/mpc/lib/:$GCC_PATH/mpfr/lib/:$GCC_PATH/gmp/lib/:$LD_LIBRARY_PATH export PATH=$GAUSSHOME/bin:$GCC_PATH/gcc/bin:$PATH3. 选择debug版进行configurecd openGauss-server ##执行编译debug版本,加上--with-libxml ./configure --gcc-version=7.3.0 CC=g++ CFLAGS='-O0' --prefix=$GAUSSHOME --3rd=$BINARYLIBS --with-libxml --enable-debug --enable-cassert --enable-thread-safety --without-readline --without-zlib ##编译安装 make -sj ##显示:All of openGauss successfully made. Ready to install.则此步成功 make install -sj ##显示:openGauss installation complete.编译成功说明:-s参数是silent模式,有些编译信息不会打印出来。如果使用-j参数,make执行的时候会一直增加并发数,有时会遇到“cannot allicate memory”的错。一般-j参数后可指定数字为 cpu数 X 2。如编译环境是4 CPU,可使用make -j8的参数进行编译。编译验证编译结束后,可按以下方式对编译后的openGauss进行验证:1. 创建omm用户赋予环境变量##root用户执行 useradd omm -g dbgrp passwd omm chown -R omm: /root/openGauss-server-3.0.0 su - omm vi ~/.bashrc export GAUSSHOME=/root/openGauss-server-3.0.0/dest/ ##编译结果的路径,可根据实际情况修改 export LD_LIBRARY_PATH=$GAUSSHOME/lib:$LD_LIBRARY_PATH export PATH=$GAUSSHOME/bin:$PATH source ~/.bashrc2. 数据库初始化和启动gs_initdb --pgdata=/home/omm/data --nodename=primary --pwpasswd=opgs@1234 --encoding=UTF-8 --locale=en_US.UTF-8 gs_ctl start -D /home/omm/data -Z single_node -l /home/omm/log/opengauss.log ##查看进程 ps -ef|grep gaussdb ##检查数据库状态 gs_ctl query -D /home/omm/data3. XML类型的支持情况gsql -d postgres -r CREATE TABLE xmltest ( id int, data xml ); INSERT INTO xmltest VALUES (1, '<value>one</value>'); INSERT INTO xmltest VALUES (2, '<value>two</value>'); openGauss=# SELECT * FROM xmltest; id | data ----+-------------------- 1 | <value>one</value> 2 | <value>two</value> (2 rows) openGauss=# SELECT xmlconcat('<foo/>', NULL, '<?xml version="1.1" standalone="no"?><bar/>'); xmlconcat -------------- <foo/><bar/> (1 row) openGauss=# SELECT xmlconcat('<?xml version="1.1"?><foo/>', NULL, '<?xml version="1.1" standalone="no"?><bar/>'); xmlconcat ----------------------------------- <?xml version="1.1"?><foo/><bar/> (1 row)
-
MOT可以根据负载的特点,显著加快应用程序的整体性能。MOT通过提高数据访问和事务执行的效率,并通过消除并发执行事务之间的锁和锁存争用,最大程度地减少重定向,从而提高了事务处理的性能。MOT的极速不仅因为它在内存中,还因为它围绕并发内存使用管理进行了优化。数据存储、访问和处理算法从头开始设计,以利用内存和高并发计算的最新先进技术。openGauss允许应用程序随意组合MOT和基于标准磁盘的表。对于启用已证明是瓶颈的最活跃、高争用和对性能敏感的应用程序表,以及需要可预测的低延迟访问和高吞吐量的表来说,MOT特别有用。MOT可用于各种应用,例如:高吞吐事务处理:这是使用MOT的主要场景,因为它支持海量事务,同时要求单个事务的延迟较低。这类应用的例子有实时决策系统、支付系统、金融工具交易、体育博彩、移动游戏、广告投放等。性能瓶颈加速:存在高争用现象的表可以通过使用MOT受益,即使该表是磁盘表。由于延迟更低、竞争和锁更少以及服务器吞吐量能力增加,此类表(除了相关表和在查询和事务中一起引用的表之外)的转换使得性能显著提升。消除中间层缓存:云计算和移动应用往往会有周期性或峰值的高工作负载。此外,许多应用都有80%以上负载是读负载,并伴有频繁的重复查询。为了满足峰值负载单独要求,以及降低响应延迟提供最佳的用户体验,应用程序通常会部署中间缓存层。这样的附加层增加了开发的复杂性和时间,也增加了运营成本。 MOT提供了一个很好的替代方案,通过一致的高性能数据存储来简化应用架构,缩短开发周期,降低CAPEX和OPEX成本。大规模流数据提取:MOT可以满足云端(针对移动、M2M和物联网)、事务处理(Transactional Processing,TP)、分析处理(Analytical Processing,AP)和机器学习(Machine Learning,ML)的大规模流数据的提取要求。MOT尤其擅长持续快速地同时提取来自许多不同来源的大量数据。这些数据可以在以后进行处理、转换,并在速度较慢的基于磁盘的表中进行移动。另外,MOT还可以查询到一致的、最新的数据,从而得出实时结果。在有许多实时数据流的物联网和云计算应用中,通常会有专门的数据摄取和处理。例如,一个Apache Kafka集群可以用来提取10万个事件/秒的数据,延迟为10ms。一个周期性的批处理任务会将收集到的数据收集起来,并将转换格式,放入关系型数据库中进行进一步分析。MOT可以通过将数据流直接存储在MOT关系表中,为分析和决策做好准备,从而支持这样的场景(同时消除单独的数据处理层)。这样可以更快地收集和处理数据,MOT避免了代价高昂的分层和缓慢的批处理,提高了一致性,增加了分析数据的实时性,同时降低了总拥有成本(Total Cost of Ownership,TCO)。降低TCO:提高资源利用率和消除中间层可以节省30%到90%的TCO。友商案例:MemSQL、Azure。
-
审计背景openGauss5 高安全新特性支持用户级别审计设置支持用户级别审计日志,对指定用户的所有SQL语句记录审计日志;支持按客户端信息配置审计开关,对指定的客户端APP及IP不记录审计日志;支持对风险较高的系统函数调用记录审计日志openGauss5给我们带我们带来很多惊喜的功能,包括内核能力增强、高性能、高智能、高可用、高安全、资源池化等等,其中笔者注意到 高安全的功能特性增强了很多。也许有些读者对审计的功能不重视,但是一款真正的企业级的数据库,如果没有审计功能一切无法谈起,下面由笔者给各位剖析。openGauss5产品定位是一个OLTP数据库,作为交易型数据库,它必须有严谨的各种机制保障交易安全。客户端发起的数据操作事关交易,可以分为交易前、交易中、交易后的阶段。交易前,在正式事务处理之前,首先把客户端的数据操作保存下来,不同的产品有不同的表达,一般会写到WAL日志上。这样当发生宕机或者不可控的断电事故,数据库重新上线的时候 ,可以从日志里面找到相关信息进行回放,正式交易。交易中主要由ACID的机制去保障客户的交易完成,这时候客户持续生成一个redo日志,交易的具体细节分成多个环节,每一个环节都会写入到redo日志,根据进行会实现倒退回滚或者重复尝试,每一个事务都会分配到唯一的事务ID。交易策略一般分为悲观策略和乐观策略,悲观策略会把每一个环节考虑到最糟糕的地步,它会不断尝试提交,不断与其它并发的事务竞争、协调,保证它是唯一的。而乐观策略会跳过多个环境 ,到了最后提交,它再与其事务协商。交易后交易完成后,数据是永久真实保存到数据库里面,不可以回退,但是数据有可能会有不可抗拒性丢失的风险。因此会有一主多备或异地容灾两地三中心的解决方案。即使发生自然界不可挡的灾难,也能保存另外一份完整的数据。最关键的是交易进行中的策略,一般业务会采用悲观策略模式,但是这样还是不够的。要把一个事情做好,事前要预防,事中要控制,事后要进行审计。数据库审计网络搜索数据库审计内容分为五块,分别是多层业务关联审计、细粒度数据库审计、精准化行为回溯、全方位风险控制、职权分离多层业务关联审计,通过应用层访问和数据库操作请求进行多层业务关联审计,实现访问者信息的完全追溯,包括:操作发生的URL、客户端的IP地址、请求报文等信息,通过多层业务关联审计能更精确地定位事件发生前后所有层面的访问及操作请求,使管理人员对用户的行为一目了然,真正做到数据库操作行为可监控,违规操作可追溯。细粒度数据库审计,通过对不同数据库的SQL语义分析,提取出SQL中相关的要素(用户、SQL操作、表、字段、视图、索引、过程、函数等),实时监控来自各个层面的所有数据库活动,包括应用系统发起的数据库操作请求、来自数据库客户端的操作请求、远程登录服务器后的操作请求等,以及通过远程命令行执行的SQL命令,并对违规的操作进行阻断。系统不仅对数据库操作请求进行实时审计,还对数据库返回结果进行完整的还原和审计,同时可以根据返回结果设置审计规则。精准化行为回溯,一旦发生安全事件,系统可提供基于数据库对象的完全自定义的审计查询及审计数据展现功能,彻底摆脱数据库的黑盒状态。全方位风险控制,灵活的策略定制:根据登录用户、源IP地址、数据库对象(分为数据库用户、表、字段)、操作时间、SQL操作命令、返回的记录数或受影响的行数、关联表数量、SQL执行结果、SQL执行时长、报文内容等的灵活组合来定义客户所关心的重要事件和风险事件。多形式的实时报警:当检测到可疑操作或违反审计规则的操作时,系统可以通过监控中心报警、短信报警、邮件报警、Syslog报警等方式通知数据库管理员。职权分离根据相关标准和规范,应对工作人员进行职责和系统设置权限划分。真实的操作过程回放对用户关心的操作可以回放整个相关过程,让审计员可以看到真实输入及屏幕显示内容。对于远程操作,能实现对精细操作内容的检索,如删除表、执行文件命令、数据搜索等。数据库审计系统的主要功能,如下1.实时监测并智能地分析、还原各种数据库操作过程。2.根据规则设定及时阻断违规操作,保护重要的数据库表和视图。3.实现对数据库系统漏洞、登录账号、登录工具和数据操作过程的跟踪,发现对数据库系统的异常使用。4.对登录用户、数据库表名、字段名及关键字等内容进行多种条件组合的规则设定,形成灵活的审计策略。
-
背景信息数据库安全对数据库系统来说至关重要。openGauss将用户对数据库的所有操作写入审计日志。数据库安全管理员可以利用这些日志信息,重现导致数据库现状的一系列事件,找出非法操作的用户、时间和内容等。关于审计功能,用户需要了解以下几点内容:审计总开关audit_enabled支持动态加载。在数据库运行期间修改该配置项的值会立即生效,无需重启数据库。默认值为on,表示开启审计功能。 除了审计总开关,各个审计项也有对应的开关。只有开关开启,对应的审计功能才能生效。 各审计项的开关支持动态加载。在数据库运行期间修改审计开关的值,不需要重启数据库便可生效。操作步骤1.以操作系统用户omm登录数据库主节点。 2.使用如下命令连接数据库。gsql -d postgres -p 80003.检查审计总开关状态。a. 用show命令显示审计总开关audit_enabled的值。SHOW audit_enabled;如果显示为off,执行“\q”命令退出数据库。b. 执行如下命令开启审计功能,参数设置立即生效。gs_guc set -N all -I all -c "audit_enabled=on"4.配置具体的审计项。说明: -只有开启审计功能,用户的操作才会被记录到审计文件中。 -各审计项的默认参数都符合安全标准,用户可以根据需要开启其他审计功能,但会对性能有一定影响。 以开启对数据库所有对象的增删改操作的审计开关为例,其他配置项的修改方法与此相同,修改配置项的方法如下所示:gs_guc reload -N all -I all -c "audit_system_object=12295"其中audit_system_object代表审计项开关,12295为该审计开关的值。
-
查询重写——rewriter查询重写利用已有语句特征和关系代数运算来生成更高效的等价语句,在数据库优化器中扮演关键角色;尤其在复杂查询中,能够在性能上带来数量级的提升,可谓是“立竿见影”的“黑科技”。SQL语言是丰富多样的,非常的灵活,不同的开发人员依据经验的不同,手写的SQL语句也是各式各样,另外还可以通过工具自动生成。同时SQL语言是一种描述性语言,数据库的使用者只是描述了想要的结果,而不关心数据的具体获取方式,输入数据库的SQL语言很难做到是以最优形式表示的,往往隐含了一些冗余信息,这些信息可以被挖掘用来生成更加高效的SQL语句。查询重写就是把用户输入的SQL语句转换为更高效的等价SQL,查询重写遵循2个基本原则:等价性:原语句和重写后的语句,输出结果相同。高效性:重写后的语句,比原语句在执行时间和资源使用上更高效。介绍openGauss如下几个关键的查询重写技术:常量表达式化简:常量表达式即用户输入SQL语句中包含运算结果为常量的表达式,分为算数表达式、逻辑运算表达式、函数表达式。查询重写可以对常量表达式预先计算以提升效率。例如“SELECT * FROM table WHERE a=1+1; ”语句被重写为“SELECT * FROM table WHERE a=2”语句。子查询提升:由于子查询表示的结构更清晰,符合人的阅读理解习惯,用户输入的SQL语句往往包含了大量的子查询,但是相关子查询往往需要使用嵌套循环的方法来实现,执行效率较低,因此将子查询优化为“Semi Join”的形式可以在优化规划时选择其它的执行方法,或能提高执行效率。例如“SELECT * FROM t1 WHERE t1.a in (SELECT t2.a FROM t2); ”语句可重写为“SELECT * FROM t1 LEFT SEMI JOIN t2 ON t1.a=t2.a”语句。谓词下推:谓词(Predicate),通常为SQL语句中的条件,例如“SELECT * FROM t1 WHERE t1.a=1; ”语句中的“t1.a=1”即为谓词。等价类(Equivalent-Class)是指等价的属性、实体等对象的集合,例如“WHERE t1.a=t2.a”语句中,t1.a和t2.a互相等价,组成一个等价类{t1.a,t2.a}。利用等价类推理(又称作传递闭包),我们可以生成新的谓词条件,从而达到减小数据量和最大化利用索引的目的。如图2所示,我们举一个形象的例子来说明谓词下推的威力。假设有两个表t1、t2;它们分别包含[1,2,3,…100]共100行数据,那么查询语句“SELECT * FROM t1 JOIN t2 ON t1.a=t2.a WHERE t1.a=1”的逻辑计划在经过查询重写前后的对比。
-
一、适用场景1)误删除表的场景; 2)需要将表中的数据恢复到指定时间点或者CSN。二、简单描述闪回恢复可以有选择的撤销已提交事务对数据库的影响,恢复速度快,只需要秒级,而且恢复速度与数据库大小无关。三、实践操作0.配置闪回相关参数 ## 旧版本保留的事务数,超过该事务数的旧版本将被回收清理 gs_guc set -N all -I all -c "version_retention_age=10000" ## 打开回收站 gs_guc set -N all -I all -c "enable_recyclebin=on" ## 置回收站对象保留时间,超过该时间的回收站对象将被自动清理 gs_guc set -N all -I all -c "recyclebin_retention_time=15min" gs_guc set -N all -I all -c "vacuum_defer_cleanup_age=10000" gs_guc set -N all -I all -c "enable_default_ustore_table=on" #重新加载使配置生效 gs_ctl reload -D /data/og1备注:ASTORE引擎暂不支持闪回DROP/TRUNCATE。1.闪回查询描述:可以查询过去某个时间点表的snapshot(快照)数据,基于MVCC多版本控制机制,通过检索查询旧版本,获取指定老版本的数据。#记录当前时间 test=# select current_timestamp; pg_systimestamp ------------------------------- 2022-03-03 11:00:46.075387+08 (1 row) #插入数据 test=# insert into test_1 values(3); INSERT 0 1 #记录插入数据之后的时间 test=# select current_timestamp; pg_systimestamp ------------------------------- 2022-03-03 11:00:58.635591+08 (1 row) #查询timestamp对应的CSN test=# select snptime,snpcsn from gs_txn_snapshot where snptime between '2022-03-03 11:00:43.075387+08' and test-# '2022-03-03 11:00:58.635591'; snptime | snpcsn -------------------------------+-------- 2022-03-03 11:00:58.513917+08 | 3134 2022-03-03 11:00:55.492238+08 | 3131 2022-03-03 11:00:52.471618+08 | 3129 2022-03-03 11:00:49.446113+08 | 3127 2022-03-03 11:00:46.424361+08 | 3125 2022-03-03 11:00:43.402865+08 | 3123 (6 rows) #执行闪回查询命令,查看闪回结果 #基于timestamp闪回查询,注意:基于时间点的闪回查询,这个时间点可以不是对应到csn点的时间, #可以是recylcebin_retention_time内的任意时间 test=# select * from test_1 timecapsule timestamp to_timestamp('2022-03-03 11:00:43.513917','YYYY-MM-DD HH24: MI:SS.FF'); id ---- 1 2 (3 rows) 此时3还没有插入 #基于csn闪回查询 test=# select * from test_1 timecapsule csn 3123; id ---- 1 2 (3 rows)2.闪回drop闪回drop:可以恢复意外删除的表#模拟删除表 [omm@OG1 ~]$ gsql -d test -p 15400 -r test=# drop table test_1; DROP TABLE #查看回收站中的内容 test=# select rcyname,rcyoriginname,rcytablespace from gs_recyclebin; rcyname | rcyoriginname | rcytablespace ------------------------------+---------------+--------------- BIN$61124EB6173$52489D18==$0 | test_1 | 0 #gs_recyclebin这个表属于pg_catalog,有很多列, #暂时先关注到rcyname:表示对象被删除时,系统生成的名称 #rcyoriginname:表示被删除对象原来的名称 #闪回恢复刚刚删除的表test_1,并为其起了名字叫test_1_bak test=# timecapsule table test_1 to before drop rename to test_1_bak; TimeCapsule Table test=# select * from test_1_bak; id ---- 1 2 3 (4 rows) #再次查看一下回收站中的内容 test=# select rcyname,rcyoriginname,rcytablespace from gs_recyclebin; rcyname | rcyoriginname | rcytablespace ---------+---------------+--------------- (0 rows) #可以发现,回收站中对于test_1的记录已经删除 #如果在删除表的时候加入了purge,那么表会被直接删除掉,而不是放到回收站中 test=# drop table test_1_bak purge; DROP TABLE test=# select rcyname,rcyoriginname,rcytablespace from gs_recyclebin; rcyname | rcyoriginname | rcytablespace ---------+---------------+--------------- (0 rows)3.闪回truncate闪回truncate:可以恢复误操作或意外truncate的表#truncate表test_2,这个表中创建有索引 test=# truncate table test_2; TRUNCATE TABLE test=# select * from test_2; id | name ----+------ (0 rows) #可以发现truncate之后表中的数据没有了 #查看回收站中的内容 test=# select rcyname,rcyoriginname,rcytablespace from gs_recyclebin; rcyname | rcyoriginname | rcytablespace ------------------------------+---------------+--------------- BIN$61124EB6168$524F90A8==$0 | test_2 | 0 BIN$61124EB616C$524F9A58==$0 | id_uniq | 0 (2 rows) #利用回收站恢复truncate掉的数据 test=# timecapsule table test_2 to before truncate; TimeCapsule Table test=# select * from test_2; id | name ----+-------- 1 | XXX 2 | XXX 3 | haha 4 | Zhang 5 | Hua 6 | AAA 7 | heihei 8 | Get (8 rows) test=# select rcyname,rcyoriginname,rcytablespace from gs_recyclebin; rcyname | rcyoriginname | rcytablespace ------------------------------+---------------+--------------- BIN$61124EB616C$52548180==$0 | id_uniq | 0 BIN$61124EB6168$52548748==$0 | test_2 | 0 (2 rows) #从上可以发现,恢复truncate掉的数据之后,回收站中还有相应的记录 #清空回收站中指定的表或索引信息 test=# purge table test_2; PURGE TABLE test=# select rcyname,rcyoriginname,rcytablespace from gs_recyclebin; rcyname | rcyoriginname | rcytablespace ---------+---------------+--------------- (0 rows) ##由于索引id_uniq附属在表test_2上,所以purge掉表的同时,也会将相关索引给purge掉
-
openGauss引入了MOT存储引擎,它是一种事务性行存储,针对多核和大内存服务器进行了优化。MOT是openGauss数据库最先进的生产级特性(Beta版本),它为事务性工作负载提供更高的性能。MOT完全支持ACID特性,并包括严格的持久性和高可用性支持。企业可以在关键任务、性能敏感的在线事务处理(OLTP)中使用MOT,以实现高性能、高吞吐、可预测低延迟以及多核服务器的高利用率。MOT尤其适合在多路和多核处理器的现代服务器上运行,例如基于Arm/鲲鹏处理器的华为TaiShan服务器,以及基于x86的戴尔或类似服务器。图 1 openGauss内存优化存储引擎如图1所示,openGauss数据库内存优化存储引擎组件(绿色部分)负责管理MOT和事务。MOT与基于磁盘的普通表并排创建。MOT的有效设计实现了几乎完全的SQL覆盖,并且支持完整的数据库功能集,如存储过程和自定义函数(限制参见MOT SQL覆盖和限制)。通过完全存储在内存中的数据和索引、非统一内存访问感知(NUMA-aware)设计、消除锁和锁存争用的算法以及查询原生编译,MOT可提供更快的数据访问和更高效的事务执行。MOT有效的几乎无锁的设计和高度调优的实现,使其在多核服务器上实现了卓越的近线性吞吐量扩展,这可能是业界最好的。MOT完全支持ACID特性:原子性(Atomicity):原子事务是一系列不可分割的数据库操作。在事务完成(分别提交或中止)之后,这些操作要么全部发生,要么全部不发生。一致性(Consistency):事务结束后,数据库处于一致状态,保留数据完整性。隔离性(Isolation):事务之间不能相互干扰。MOT支持不同的重复读和读提交隔离级别。在下一个版本中,MOT还将支持可序列化隔离。更多信息,请参见MOT隔离级别。持久性(Durability):即使发生崩溃和失败,成功完成(提交)的事务效果持久保存。MOT完全集成了openGauss的基于WAL的日志记录。同时支持同步和异步日志记录选项。MOT还支持同步+面向NUMA优化的组提交。更多信息,请参见MOT持久性概念。
-
实验环境操作系统: CentOS 7.6 数据库版本: openGauss 1.1.0 Primary 主机/IP: opengaussdb1/192.168.1.11 (openGauss主备已部署完毕) Standby 主机/IP: opengaussdb2/192.168.1.12 (openGauss主备已部署完毕)Tips: 不建议在云环境(如:华为云)下搭建Keepalived进行测试,本人在云环境下测试发现,Keepalived的VIP无法在云环境下与其他主机通信,云环境下如何使用该VIP建议咨询云服务厂商。在踩坑之后,选择使用本地的VMWare workstation进行简单测试。1. 安装KeepAlived软件## 在所有节点执行安装 yum install keepalived -y2. 配置keepalivedTips: 采用nopreempt不抢占VIP,主备节点的state均设置为BACKUP。主节点配置文件# vi /etc/keepalived/keepalived.conf -------------------------------------------- ! Configuration File for keepalived ## 全局定义 global_defs { router_id Keepalived_openGauss #运行 keepalived 服务器的一个标识 script_user root #执行脚本的用户 } ## VRRP实例定义 ## 通常如果master服务Down掉后backup会变成master,但是当master服务又好了的时候 master此时会抢占VIP,这样就会发生两次数据库切换。 ## 建议使用nopreempt参数设置为非抢占模式,此时主库从故障中恢复后,不会从新的主库抢回VIP,但这需要将master和backup的state都设置成backup。 vrrp_instance VI_1 { state BACKUP #指定Keepalived的角色(BACKUP需大写) interface eth0 #指定 HA 监测的网络接口 virtual_router_id 59 #虚拟路由的数字标识,同一个 vrrp_instance 下,MASTER 和 BACKUP 一致 nopreempt #非抢占模式,主库从故障中恢复后,不会从新的主库抢回VIP priority 100 #优先级,备节点需要适当降低优先级 advert_int 1 #MASTER 和 BACKUP 负载均衡器同步检查的时间间隔(秒) authentication { #设置验证码和验证类型 auth_type PASS auth_pass 1111 } virtual_ipaddress { #设置虚拟 IP 地址,可以设置多个,每个一行 192.168.1.10 } } ## 虚拟服务器定义 virtual_server 192.168.1.10 26000 { #设置虚拟服务器的 IP 和端口,用空格隔开 delay_loop 6 #设置运行情况检查时间,单位是秒 # lb_algo rr #负载调度算法(轮询) # lb_kind DR #负载均衡机制(NAT、TUN、DR) persistence_timeout 50 #会话保持时间(秒) protocol TCP #转发协议类型 real_server 192.168.1.11 26000 { #配置服务节点 weight 100 #配置服务节点的权重 notify_down /gauss/failoverdb.sh #故障响应脚本 TCP_CHECK { #使用TCP_CHECK方式进行健康检查 connect_timeout 10 #10秒无响应即超时 delay_before_retry 3 #重试间隔时间 } } } --------------------------------------------主节点故障切换脚本(仅适用openGauss进程崩溃故障处理,不适用Primary操作系统宕机故障处理)vi /gauss/failoverdb.sh -------------------------------------------- #!/bin/bash echo "Start to failover openGauss database." pkill keepalived ssh 192.168.1.12 "su - omm -c 'gs_ctl failover -D /gauss/data/db1'" ssh 192.168.1.12 "su - omm -c 'gs_om -t refreshconf'" echo 'Failover operation is completed.' -------------------------------------------- chmod 764 /gauss/failoverdb.sh备节点配置文件# vi /etc/keepalived/keepalived.conf -------------------------------------------- ! Configuration File for keepalived ## 全局定义 global_defs { router_id Keepalived_openGauss #运行 keepalived 服务器的一个标识 script_user root #执行脚本的用户 } ## VRRP实例定义 ## 通常如果master服务Down掉后backup会变成master,但是当master服务又好了的时候 master此时会抢占VIP,这样就会发生两次数据库切换。 ## 建议使用nopreempt参数设置为非抢占模式,此时主库从故障中恢复后,不会从新的主库抢回VIP,但这需要将master和backup的state都设置成backup。 vrrp_instance VI_1 { state BACKUP #指定Keepalived的角色(BACKUP需大写) interface eth0 #指定 HA 监测的网络接口 virtual_router_id 59 #虚拟路由的数字标识,同一个 vrrp_instance 下,MASTER 和 BACKUP 一致 nopreempt #非抢占模式,主库从故障中恢复后,不会从新的主库抢回VIP priority 60 #优先级,备节点需要适当降低优先级 advert_int 1 #MASTER 和 BACKUP 负载均衡器同步检查的时间间隔(秒) authentication { #设置验证码和验证类型 auth_type PASS auth_pass 1111 } virtual_ipaddress { #设置虚拟 IP 地址,可以设置多个,每个一行 192.168.1.10 } } ## 虚拟服务器定义 virtual_server 192.168.1.10 26000 { #设置虚拟服务器的 IP 和端口,用空格隔开 delay_loop 6 #设置运行情况检查时间,单位是秒 # lb_algo rr #负载调度算法(轮询) # lb_kind DR #负载均衡机制(NAT、TUN、DR) persistence_timeout 50 #会话保持时间(秒) protocol TCP #转发协议类型 real_server 192.168.1.12 26000 { #配置服务节点 weight 60 #配置服务节点的权重 notify_down /gauss/failoverdb.sh #虚拟服务故障响应脚本 MISC_CHECK { ## 使用 MISC_CHECK 方式自定义脚本做健康检查 misc_path "/gauss/check.sh" ## 检测脚本 misc_timeout 10 ## 执行脚本的超时时间 misc_dynamic ## 根据退出状态码动态调整服务器的权重 } } } -------------------------------------------- ## 备节点选择MISC_CHECK方式的原因: ## 测试发现,当主节点直接断电宕机后,Keepalived的VIP会漂移至备节点,此时如果使用TCP_CHECK方式做健康检查,会因为备机可读的原因使得VIP:26000连接正常,造成keepalived健康检查的误判。 ## 最终导致主节点断电宕机后,备节点虽获取了VIP,但并没有执行openGauss的failover操作,备节点依旧只读,无法对外提供业务。 ## 为了纠正这一点,建议使用MISC_CHECK方式自定义脚本,登录主节点做数据库健康检查(简单示例脚本:/gauss/check.sh)备节点健康检查脚本[ ssh登录主节点进行数据库连接检查 ]vi /gauss/check.sh ------------------------------------------- ssh 192.168.1.11 "su - omm -c \"gsql -d postgres -p 26000 -t -A -c 'select 1;'\"" -------------------------------------------备节点故障切换脚本vi /gauss/failoverdb.sh -------------------------------------------- #!/bin/bash echo "Start to failover openGauss database." pkill keepalived su - omm -c "gs_ctl failover -D /gauss/data/db1" su - omm -c "gs_om -t refreshconf" echo 'Failover operation is completed.' -------------------------------------------- chmod 764 /gauss/failoverdb.sh3. openGauss配置修改openGauss监听地址$ gs_guc set -I all -N all -c "listen_addresses = '0.0.0.0'" $ gs_guc set -I all -N all -c "local_bind_address = '0.0.0.0'"修改所有节点replconninfo参数(避免端口冲突)$ vi /gauss/data/db1/postgresql.conf -------------------------------------------- 修改:localport --> 26011 修改:remoteport --> 26011 --------------------------------------------重启openGauss数据库,并检查服务器状态## 重启openGauss [omm@prod db1]$ gs_om -t stop && gs_om -t start ## 检查openGauss状态 [root@opengaussdb1 ~]# su - omm -c "gs_om -t status --detail" [ Cluster State ] cluster_state : Normal redistributing : No current_az : AZ_ALL [ Datanode State ] node node_ip instance state | ----------------------------------------------------------------------- 1 opengaussdb1 192.168.1.11 6001 /gauss/data/db1 P Primary Normal | 2 opengaussdb2 192.168.1.12 6002 /gauss/data/db1 S Standby Normal ## 检查KeepAlived进程状态 [omm@opengaussdb1 ~]$ ps -ef|grep keep|grep -v grep root 15664 1 0 16:15 ? 00:00:00 /usr/sbin/keepalived -D root 15665 15664 0 16:15 ? 00:00:00 /usr/sbin/keepalived -D root 15666 15664 0 16:15 ? 00:00:00 /usr/sbin/keepalived -D ## 检查VIP状态 [root@opengaussdb1 ~]# ip a 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 00:0c:29:da:60:c0 brd ff:ff:ff:ff:ff:ff inet 192.168.1.11/24 brd 192.168.1.255 scope global noprefixroute ens33 valid_lft forever preferred_lft forever inet 192.168.1.10/32 scope global ens33 ## VIP:192.168.1.10 valid_lft forever preferred_lft forever inet6 2408:8270:237:ded0:c89c:adab:e7b:8bd6/64 scope global noprefixroute dynamic valid_lft 258806sec preferred_lft 172406sec inet6 fe80::c4f2:8ad1:200d:ce9b/64 scope link noprefixroute valid_lft forever preferred_lft forever4. 故障模拟测试主节点[192.168.1.11]操作## kill数据库进程 [root@opengaussdb1 ~]# ps -ef|grep gauss omm 18115 1 4 16:30 ? 00:00:35 /gauss/app/bin/gaussdb -D /gauss/data/db1 -M primary root 19254 9299 0 16:42 pts/0 00:00:00 grep --color=auto gauss [root@opengaussdb1 ~]# kill -9 18115 ## 检查message日志[检测到故障,执行notify_down脚本,并关闭keepalived服务] # tail -fn 200 /var/log/messages Feb 19 16:42:57 opengaussdb1 Keepalived_healthcheckers[18816]: TCP connection to [192.168.1.11]:26000 failed. Feb 19 16:43:00 opengaussdb1 Keepalived_healthcheckers[18816]: TCP connection to [192.168.1.11]:26000 failed. Feb 19 16:43:00 opengaussdb1 Keepalived_healthcheckers[18816]: Check on service [192.168.1.11]:26000 failed after 1 retry. Feb 19 16:43:00 opengaussdb1 Keepalived_healthcheckers[18816]: Removing service [192.168.1.11]:26000 from VS [192.168.1.10]:26000 Feb 19 16:43:00 opengaussdb1 Keepalived_healthcheckers[18816]: IPVS (cmd 1160, errno 2): No such destination Feb 19 16:43:00 opengaussdb1 Keepalived_healthcheckers[18816]: Executing [/gauss/failoverdb.sh] for service [192.168.1.11]:26000 in VS [192.168.1.10]:26000 Feb 19 16:43:00 opengaussdb1 Keepalived_healthcheckers[18816]: Lost quorum 1-0=1 > 0 for VS [192.168.1.10]:26000 Feb 19 16:43:00 opengaussdb1 Keepalived[18815]: Stopping Feb 19 16:43:00 opengaussdb1 Keepalived_healthcheckers[18816]: pid 19258 exited due to signal 15 Feb 19 16:43:00 opengaussdb1 Keepalived_vrrp[18817]: VRRP_Instance(VI_1) sent 0 priority Feb 19 16:43:00 opengaussdb1 Keepalived_vrrp[18817]: VRRP_Instance(VI_1) removing protocol VIPs. Feb 19 16:43:00 opengaussdb1 Keepalived_healthcheckers[18816]: IPVS (cmd 1156, errno 2): No such file or directory Feb 19 16:43:00 opengaussdb1 Keepalived_healthcheckers[18816]: Stopped Feb 19 16:43:01 opengaussdb1 Keepalived_vrrp[18817]: Stopped Feb 19 16:43:01 opengaussdb1 Keepalived[18815]: Stopped Keepalived v1.3.5 (03/19,2017), git commit v1.3.5-6-g6fa32f2备节点[192.168.1.12]检查## 检查VIP是否已漂移 [root@opengaussdb2 ~]# ip a|grep 192.168 inet 192.168.1.12/24 brd 192.168.1.255 scope global noprefixroute ens33 inet 192.168.1.10/32 scope global ens33 ## 检查数据库状态[已failover成为Primary] [omm@opengaussdb2 ~]$ gs_om -t status --detail [ Cluster State ] cluster_state : Degraded redistributing : No current_az : AZ_ALL [ Datanode State ] node node_ip instance state | --------------------------------------------------------------------------------- 1 opengaussdb1 192.168.1.11 6001 /gauss/data/db1 P Down Manually stopped | 2 opengaussdb2 192.168.1.12 6002 /gauss/data/db1 S Primary Normal
-
用户使用CREATE USER和ALTER USER可以创建和管理数据库用户。openGauss包含一个或多个已命名数据库。用户和角色在整个openGauss范围内是共享的,但是其数据并不共享。即用户可以连接任何数据库,但当连接成功后,任何用户都只能访问连接请求里声明的那个数据库。非三权分立下,openGauss用户帐户只能由系统管理员或拥有CREATEROLE属性的安全管理员创建和删除。三权分立时,用户帐户只能由初始用户和安全管理员创建。在用户登录openGauss时会对其进行身份验证。用户可以拥有数据库和数据库对象(例如表),并且可以向用户和角色授予对这些对象的权限以控制谁可以访问哪个对象。除系统管理员外,具有CREATEDB属性的用户可以创建数据库并授予对这些数据库的权限。创建、修改和删除用户要创建用户,请使用SQL语句CREATE USER。 例如:创建用户joe,并设置用户拥有CREATEDB属性。postgres=# CREATE USER joe WITH CREATEDB PASSWORD "Bigdata@123"; CREATE ROLE要创建系统管理员,请使用带有SYSADMIN选项的CREATE USER语句 。要删除现有用户,请使用DROP USER。要更改用户帐户(例如,重命名用户或更改密码),请使用ALTER USER。要查看用户列表,请查询视图PG_USER:SELECT * FROM pg_user; 要查看用户属性,请查询系统表PG_AUTHID:SELECT * FROM pg_authid; 私有用户对于有多个业务部门,各部门间使用不同的数据库用户进行业务操作,同时有一个同级的数据库维护部门使用数据库管理员进行维护操作的场景下,业务部门可能希望在未经授权的情况下,管理员用户只能对各部门的数据进行控制操作(DROP、ALTER、TRUNCATE),但是不能进行访问操作(INSERT、DELETE、UPDATE、SELECT、COPY)。即针对管理员用户,表对象的控制权和访问权要能够分离,提高普通用户数据安全性。三权分立情况下,管理员对其他用户放在属于各自模式下的表无权限。但是,这种无权限包含了无控制权限,因此不能满足上面的诉求。为此,openGauss提供了私有用户方案。即在非三权分立模式下,创建具有INDEPENDENT属性的私有用户。CREATE USER user_independent WITH INDEPENDENT IDENTIFIED BY "1234@abc";针对该用户的对象,系统管理员和拥有CREATEROLE属性的安全管理员在未经其授权前,只能进行控制操作(DROP、ALTER、TRUNCATE),无权进行INSERT、DELETE、SELECT、UPDATE、COPY、GRANT、REVOKE、ALTER OWNER操作。
-
openGauss主要包含18个代码仓,引用开源软件的补丁代码仓、JDBC驱动代码仓、ODBC驱动代码仓、数据库服务器代码仓、自治运维平台DBMind代码仓、数据库OM管理工具、数据库CM管理工具代码仓、数据库DMS代码仓、数据库DSS代码仓、数据库DCF代码仓、数据库DCC代码仓、数据库插件代码仓、MySQL到openGauss全量迁移工具代码仓、MySQL增量迁移代码仓、数据校验代码仓、数据库prometheus-exporter代码仓、监控插件生成工具代码仓和文档仓库:开源软件代码仓:https://gitee.com/opengauss/openGauss-third_partyJDBC驱动代码仓:https://gitee.com/opengauss/openGauss-connector-jdbcODBC驱动代码仓:https://gitee.com/opengauss/openGauss-connector-odbc数据库服务器代码仓:https://gitee.com/opengauss/openGauss-server自治运维平台DBMind代码仓:https://gitee.com/opengauss/openGauss-DBMind数据库OM工具代码仓:https://gitee.com/opengauss/openGauss-OM数据库CM(Cluster Manager)工具代码仓:https://gitee.com/opengauss/CM数据库DMS(Distributed Memory Service)组件代码仓: https://gitee.com/opengauss/DMS数据库DSS(Distributed Storage Service)组件代码仓: https://gitee.com/opengauss/DSS数据库DCF(Distributed Consensus Framework)代码仓:https://gitee.com/opengauss/DCF数据库DCC(Distributed Configuration Center)代码仓:https://gitee.com/opengauss/DCC数据库插件代码仓:https://gitee.com/opengauss/PluginMySQL到openGauss全量迁移工具代码仓:https://gitee.com/opengauss/openGauss-tools-chameleonMySQL增量迁移工具代码仓(包含反向迁移):https://gitee.com/opengauss/openGauss-tools-onlineMigration-mysql数据校验工具代码仓:https://gitee.com/opengauss/openGauss-tools-datachecker-performance数据库prometheus-exporter代码仓:https://gitee.com/opengauss/openGauss-prometheus-exporter数据库监控插件生成工具代码仓:https://gitee.com/opengauss/openGauss-tools-monitor数据库文档仓库:https://gitee.com/opengauss/docs
-
1.gsql 版本2.原始数据3.导出后的数据4.使用的语句./gsql -h 127.0.0.1 -p25308 -d database -U user -W password -C "\COPY (select * FROM table where age = '23' and custnm like '\"傅') to /gaussdb_ data.dat delimiter ',' csv header"
上滑加载中
推荐直播
-
HDC深度解读系列 - Serverless与MCP融合创新,构建AI应用全新智能中枢2025/08/20 周三 16:30-18:00
张昆鹏 HCDG北京核心组代表
HDC2025期间,华为云展示了Serverless与MCP融合创新的解决方案,本期访谈直播,由华为云开发者专家(HCDE)兼华为云开发者社区组织HCDG北京核心组代表张鹏先生主持,华为云PaaS服务产品部 Serverless总监Ewen为大家深度解读华为云Serverless与MCP如何融合构建AI应用全新智能中枢
回顾中 -
关于RISC-V生态发展的思考2025/09/02 周二 17:00-18:00
中国科学院计算技术研究所副所长包云岗教授
中科院包云岗老师将在本次直播中,探讨处理器生态的关键要素及其联系,分享过去几年推动RISC-V生态建设实践过程中的经验与教训。
回顾中 -
一键搞定华为云万级资源,3步轻松管理企业成本2025/09/09 周二 15:00-16:00
阿言 华为云交易产品经理
本直播重点介绍如何一键续费万级资源,3步轻松管理成本,帮助提升日常管理效率!
回顾中
热门标签