-
【摘要】 GaussDB(DWS)SQL On Anywhere特性可以实现与其他大数据组件和数据库互联互通,扩大了其数据分析的应用场景,并且可以实现冷热数据分离,分别存储在不同成本的介质上,从而降低用户成本。本文着重介绍了GaussDB(DWS)SQL On Anywhere的内部三种实现方式FDW、ELK和EC+ODBC技术,并对比其优缺点,及其整个特性的未来规划。1. 什么是SQL On Anywhere?查询分析是大数据要解决的核心问题之一,虽然大数据相关的处理引擎组件种类繁多,并提供了丰富的接口供用户使用,但相对传统数据库用户来说,SQL语言依然是使用最简单、最广泛和方便的一种接口。如果能在一个客户端中使用SQL语句操作不同的大数据组件,将极大提升使用各种大数据组件的效率。GaussDB(DWS)的SQL On Anywhere,主要指对大数据的文件系统和与其他异构数据库的访问和交互,构筑起统一的大数据计算平台。大数据文件系统主要包括HDFS和OBS,其他异构数据库主要包括Oracle、Spark和Other GaussDB(DWS)。2. GaussDB(DWS)SQL On Anywhere的作用及其应用场景通过SQL On Anywhere特性可以实现与其他大数据组件和数据库互联互通访问,可以直接同时处理本地和HDFS/OBS上的数据集,甚至其他异构数据库的数据,而无需导入导出数据,将其分析能力从本地存储扩展到数据湖中,扩大GaussDB DWS的大数据分析的应用场景;通过该特性可以帮助客户实现冷热数据分离,将使用频度更高的热数据存储在本地,而使用频度更低的冷数据存储在成本更低廉的共享存储HDFS或者DWS上,降低用户成本。从应用场景来看,可以满足如下业务需求:针对多数据源需要构建虚拟的统一数据仓库,实现多数据源联邦查询,跨数据仓库热数据和HDFS/OBS冷数据的复杂混合查询,需要提供一致的、熟悉的数据仓库操作体验。满足低频的业务全数据的低成本低延迟即席查询。3. GaussDB(DWS)SQL On Anywhere的实现方式GaussDB(DWS)SQL On Anywhere针对大数据的文件系统的访问主要通过FDW或ELK机制实现的,而跨数据库的访问主要通过EC+ODBC的方式实现的。 3.1 利用FDW访问HDFS/OBS数据GaussDB(DWS)对存储在HDFS上的Hadoop或者OBS原生数据的访问,采用FDW(Foreign Data Wrapper)机制,也称外表机制。首先通过创建Foreign Data Server来定义对HDFS数据源或同构其他集群的连接信息;之后创建Foreign Table,用于在GaussDB A数据库内部系统表中,定义对应的HDFS数据源上Hadoop原生结构化数据表的结构或对应同构其他集群结构化数据表的结构。例如读取hdfs上的数据,其流程如下: 1)建立一个hdfs_server,其中hdfs_fdw为数据库中存在的foreign data wrapper。--创建hdfs_server。postgres=# CREATE SERVER hdfs_server FOREIGN DATA WRAPPER HDFS_FDW OPTIONS (address '10.146.187.231:8000,10.180.157.130:8000' , hdfscfgpath '/opt/hadoop_client/HDFS/hadoop/etc/hadoop', type 'HDFS') ; 2)创建一个hdfs外表读取hdfs上的数据CREATE FOREIGN TABLE region ( R_REGIONKEY INT4, R_NAME TEXT, R_COMMENT TEXT )SERVER hdfs_server OPTIONS( FORMAT 'orc', FOLDERNAME '/user/hive/warehouse/mppdb.db/region_orc11_64stripe/')DISTRIBUTE BY roundrobin; 3)查询HDFS外表,例如:select * from region limit 10;目前外表支持与普通表进行关联查询,并支持多种文件存储格式,其支持的文件格式如下:文件系统读支持的文件格式写支持的文件格式HDFSORC、Parquet、TEXT、CSVORC、TEXT、CSVOBSORC、Carbondata、TEXT、CSVORC、TEXT、3.2 通过ELK访问HDFSELK的方式类似于HAWQ,它是通过建立表空间为HDFS表空间,直接将数据存储和访问HDFS文件系统,目前只支持访问HDFS文件系统,而不支持访问OBS上的数据。首先通过创建HDFS表空间,然后会创建一个HDFS表,在创建时指定表空间为HDFS表空间,最后对HDFS表的操作如同普通表的操作,可进行插入修改删除数据。以GaussDB数据库数据推到HDFS中 1)在数据库中创建HDFS表空间CREATE TABLESPACE hdfs_table RELATIVE LOCATION ‘tmp/hdtest’With (filesystem=’hdfs’, address=’28.4.136.221:9000’, cfgpath=’/opt/Huawei/bigdata/mppdb/hdfs_conf/zhndnrop/omm@HADOOP.COM/’, storepath=’/tmp/test’); 2)数据库中创建HDFS表CREATE TABLE abc( zjxxlh char(20), nbbsh char(20), khwybh char(20), zjlx char(20))WITH (orientation=orc) TABLESPACE tables_hdfs; 3)向表中插入数据insert into abc select * from region10;3.3基于EC+ODBC的跨集群访问数据GaussDB(DWS)支持通过 EC(全称Extension Connector)+ODBC统一访问其它大数据组件——将SQL发给其它大数据组件并接收执行结果,实现跨集群访问数据。目前EC+ODBC为用户提供了三种功能: SQL on Oracle、SQL on Spark和SQL on other GaussDB,分别用于连接Oracle数据库、Spark集群和其他GaussDB集群。EC+ODBC的基本工作原理是:用户首先构建Data Source对象(其中包含目标库的一些连接信息和字符编码方式),然后用户获取该Data Source的使用权限,最后通过标准ODBC API连接目标库,发送SQL语句并获取执行结果。为了方便使用,EC+ODBC为用户提供了统一的连接函数exec_on_extension(text, text)。其中,第一个参数为Data Source名称,第二个参数为发送的SQL语句,例如:postgres=# SELECT * FROM exec_on_extension('ds_spark', 'select * from a;') AS (c1 int);4 . GaussDB(DWS) SQL On Anywhere的实现方式优缺点对比方式数据源优势劣势EC+ODBCORACLESparkMPPDB1.使用灵活2.可以下推很复杂的查询到其他数据库3.支持和本地多表join1.查询得到的数据和本地join须通过stream,存在较大网络开销,查询操作执行的节点存在单点瓶颈2.配置繁琐,依赖odbc驱动,兼容性问题较多FDWHDFSOBS1.支持多DN并发查询2.支持和本地多表join等复杂查询3.支持analyze收集统计信息4.格式支持丰富,易扩展1. 无法在一张外表,同时支持读和写2. 不支持增量写,只支持覆盖写,不支持update和delete3. 不支持和本地表join的复杂查询结果直接写入外表ELKHDFS1. 支持多DN并发查询2. 支持和本地多表join查询和写入3. 支持analyze收集统计信息4. 节点本地化效率相对比较高5. 支持增量写,支持update和delete1. HDFS表空间方式要求HDFS集群与MPPDB集群有强依赖关系,不易于扩展2. 格式支持有限,目前只支持ORC格式,并且只支持访问HDFS文件系统3. 有可能会产生大量小文件5. GaussDB(DWS)未来规划GaussDB(DWS)未来规划主要仍然围绕互联互通和数据冷热存储开展,主要扩实现自动的冷热数据管理机制和扩展外表的功能:实现冷热数据的自动管理;同一个外表同时支持读写功能;外表支持更多的文件格式;外表支持将复杂查询的查询结果直接写入外表;外表支持增量写。原文链接:https://bbs.huaweicloud.com/blogs/237721【推荐阅读】【最新活动汇总】DWS活动火热进行中,互动好礼送不停(持续更新中) HOT 【博文汇总】GaussDB(DWS)博文汇总1,欢迎大家交流探讨~(持续更新中)【维护宝典汇总】GaussDB(DWS)维护宝典汇总贴1,欢迎大家交流探讨(持续更新中)【项目实践汇总】GaussDB(DWS)项目实践汇总贴,欢迎大家交流探讨(持续更新中)【DevRun直播汇总】GaussDB(DWS)黑科技直播汇总,欢迎大家交流学习(持续更新中)【培训视频汇总】GaussDB(DWS) 培训视频汇总,欢迎大家交流学习(持续更新中)扫码关注我哦,我在这里↓↓↓
-
1.GaussDB AZ内单点故障RTO(Recovery Time Objective,RTO)恢复时间目标,指在故障或灾难发生之后业务恢复时间,主要指的是所能容忍的应用停止服务的最长时间,也就是从灾难发生到业务系统恢复服务功能所需要的最短时间周期;GaussDB(DWS) AZ内的单实例和单节点故障情况下,RTO=0,是通过单点故障自恢复和SQL语句出错自动重试实现的。1)单点故障自恢复GaussDB(DWS)高可用架构采用主备从架构,之前已经有很多博文对该架构进行了详细的介绍,这里简单进行普及:集群正常情况下,主机和备机之间通过日志复制和数据页复制强同步,主机和从备之间只保持连接,不同步数据,当备机发生故障时,主机自动感知,主机与从备开始进行日志和数据页的强同步;如果是主机发生故障,通过集群管理感知,并仲裁备生主,新主与从备进行日志和数据页的强同步;因此,同环内发生单点故障的情况下,仍然时刻保证了数据的2个副本强同步,不会影响服务的可用性;2)CN Retry功能GaussDB(DWS)支持在SQL语句执行出错时的自动重试功能(下文简称CN Retry)。对于来自gsql客户端、JDBC、ODBC驱动的SQL语句,在SQL语句执行失败时,CN端能够自动识别语句执行过程中的报错,并重新下发任务进行自动重试。CN Retry功能是默认开启的,由GUC参数max_query_retry_times进行控制,支持范围是0-20,默认为6,代表可语句出错时会自动重试6次,0代表关闭该功能,GaussDB(DWS)绝大部分错误类型都支持CN Retry功能,比如主机单点故障,业务断连的情况。GaussDB(DWS) 主要是通过以上2个特性来保证单点故障业务不中断,当某个DN主机故障时,通过集群管理和高可用的单点故障自恢复,自动备机升主,此时客户业务虽然实际产生短暂的断连,通过CN Retry功能对业务在后台进行重新下发执行,客户除了感知到短暂业务缓慢,不会影响业务执行。2.GaussDB(DWS)单点故障实测我们通过以下步骤对该功能进行简单测试:1)准备压测程序模拟用户业务,探测程序方便观察业务情况;压测程序可以任意选定,模拟一定的业务压力即可。探测程序,大概如下,观测较方便:dbname=rep_hangport=28308for((i=1;i<=10000000;i++))doecho "########## current times: $i ##########"echo `date`gsql -p $port $dbname -c "insert into test_row select nextval('seq_test_001'),now() returning *;"done启动业务后的压力情况:top - 21:53:56 up 63 days, 19:11, 2 users, load average: 47.09, 23.51, 9.65Tasks: 1258 total, 2 running, 754 sleeping, 0 stopped, 0 zombie%Cpu(s): 37.6 us, 9.3 sy, 0.0 ni, 50.6 id, 1.8 wa, 0.0 hi, 0.8 si, 0.0 stKiB Mem : 40132032+total, 36850240 free, 19214592 used, 34525548+buff/cacheKiB Swap: 4194240 total, 4194240 free, 0 used. 28847993+avail Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 54439 mpp651 20 0 82.6g 4.3g 1.9g S 1914 1.1 212:44.01 gaussdb 54427 mpp651 20 0 78.3g 4.4g 1.9g S 1540 1.1 200:15.33 gaussdb 54382 mpp651 20 0 56.5g 1.8g 1.0g S 371.1 0.5 686:57.20 gaussdb 54404 mpp651 20 0 54.4g 1.6g 1.2g S 172.4 0.4 89:12.34 gaussdb 54421 mpp651 20 0 55.0g 1.6g 1.2g S 167.1 0.4 93:04.60 gaussdb 2)对单个主机节点注入网络故障ifconfig enp131s0 down3) 观察探测程序########## current times: 150 ##########Sun Jan 10 22:43:01 CST 2021 id | time1 -------+---------------------------- 95026 | 2021-01-10 22:43:01.052801(1 row)INSERT 0 1########## current times: 151 ##########Sun Jan 10 22:43:01 CST 2021 id | time1 -------+---------------------------- 95028 | 2021-01-10 22:43:01.081416(1 row)INSERT 0 1########## current times: 152 ##########Sun Jan 10 22:43:01 CST 2021 id | time1 -------+---------------------------- 95031 | 2021-01-10 22:44:05.251098(1 row)INSERT 0 1########## current times: 153 ##########Sun Jan 10 22:43:32 CST 2021 id | time1 -------+---------------------------- 95032 | 2021-01-10 22:44:05.288718(1 row)可以观测到,业务未发生断连,短暂的卡住了一分钟后继续快速执行。 卡住的时间主要和当时集群的业务压力,以及作业类型,和正在执行的语句执行到了什么阶段相关,这里业务压力比较大。结论:GaussDB(DWS) AZ内的单实例和单节点故障情况下,业务不中断。原文链接:https://bbs.huaweicloud.com/blogs/236561【推荐阅读】【最新活动汇总】DWS活动火热进行中,互动好礼送不停(持续更新中) HOT 【博文汇总】GaussDB(DWS)博文汇总1,欢迎大家交流探讨~(持续更新中)【维护宝典汇总】GaussDB(DWS)维护宝典汇总贴1,欢迎大家交流探讨(持续更新中)【项目实践汇总】GaussDB(DWS)项目实践汇总贴,欢迎大家交流探讨(持续更新中)【DevRun直播汇总】GaussDB(DWS)黑科技直播汇总,欢迎大家交流学习(持续更新中)【培训视频汇总】GaussDB(DWS) 培训视频汇总,欢迎大家交流学习(持续更新中)扫码关注我哦,我在这里↓↓↓
-
【摘要】 GaussDB(DWS) 数据库加密是DWS服务与KMS(密钥管理服务)服务的无缝对接,DWS服务通过KMS对GaussDB(DWS)进行密钥管理,起到了保护DWS数据库的作用。GuassDB(DWS) 为集群启用数据库加密,保护静态数据。当为集群启用加密时,该集群机器快照的数据都会得到加密。加密是集群一项可选且不可变的设置,要从未加密的集群更改为加密集群,必须从现有集群导出数据,然后在已启用数据库加密的新集群中重新导入这些数据,数据库加密是GaussDB(DWS)写入数据时对数据进行加密,而在用户查询数据时,DWS将数据自动进行解密后再将结果返回给用户。一、GaussDB(DWS) 服务控制台数据库加密页面:1、进入GaussDB(DWS) 服务 “购买数据仓库集群” 页面。2、在上图的页面中找到“高级配置”,并点击“自定义”。 3、打开加密数据库按钮,并选择填入密钥。4、如果没有可用的密钥,在点击“创建密钥”。5、在创建密钥的页面中填入别名和描述,点击“确定”按钮,密钥创建完成。6、创建完成后,选择使用得到的密钥去创建DWS集群。二、KMS服务加密GaussDB(DWS) 数据库 当选择KMS(密钥管理服务)对GaussDB(DWS) 进行密钥管理时,加密密钥层次结构有三层。按层次结构顺序排列,这些密钥为主密钥(CMK)、集群加密密钥 (CEK)、数据库加密密钥 (DEK)。主密钥用于给CEK加密,保存在KMS中。CEK用于加密DEK,CEK明文保存在GaussDB(DWS) 集群内存中,密文保存在GaussDB(DWS) 服务中。DEK用于加密数据库中的数据,DEK明文保存在GaussDB(DWS) 集群内存中,密文保存在GaussDB(DWS) 服务中。密钥使用流程如下:用户选择主密钥。GaussDB(DWS) 随机生成CEK和DEK明文。KMS使用用户所选的主密钥加密CEK明文并将加密后的CEK密文导入到GaussDB(DWS) 服务中。GaussDB(DWS) 使用CEK明文加密DEK明文并将加密后的DEK密文保存到GaussDB(DWS) 服务中。GaussDB(DWS) 将DEK明文传递到集群中并加载到集群内存中。当该集群重启时,集群会自动通过API向GaussDB(DWS) 请求DEK明文,GaussDB(DWS) 将CEK、DEK密文加载到集群内存中,再调用KMS使用主密钥CMK来解密CEK,并加载到集群内存中,最后用CEK明文解密DEK,并加载到集群内存中,返回给集群。三、加密密钥轮转 加密密钥轮转是指更新保存在GaussDB(DWS) 服务的密文。在GaussDB(DWS) 中,您可以轮转已加密集群的加密密钥CEK。密钥轮转流程如下:GaussDB(DWS) 集群启动密钥轮转。GaussDB(DWS) 根据集群的主密钥来解密保存在GaussDB(DWS) 服务中的CEK密文,获取CEK明文。用获取到的CEK明文解密保存在GaussDB(DWS) 服务中的DEK密文,获取DEK明文。GaussDB(DWS) 重新生成新的CEK明文。GaussDB(DWS) 用新的CEK明文加密DEK并将DEK密文保存在GaussDB(DWS) 服务中。用主密钥加密新的CEK明文并将CEK密文保存在GaussDB(DWS) 服务中。 根据业务需求和数据类型计划多久轮转一次加密密钥。为了提高数据的安全性,建议用户定期执行轮转密钥以避免密钥被破解的风险。一旦密钥可能已泄露,需要及时轮转密钥。原文链接:https://bbs.huaweicloud.com/blogs/233111【推荐阅读】【最新活动汇总】DWS活动火热进行中,互动好礼送不停(持续更新中) HOT 【博文汇总】GaussDB(DWS)博文汇总1,欢迎大家交流探讨~(持续更新中)【维护宝典汇总】GaussDB(DWS)维护宝典汇总贴1,欢迎大家交流探讨(持续更新中)【项目实践汇总】GaussDB(DWS)项目实践汇总贴,欢迎大家交流探讨(持续更新中)【DevRun直播汇总】GaussDB(DWS)黑科技直播汇总,欢迎大家交流学习(持续更新中)【培训视频汇总】GaussDB(DWS) 培训视频汇总,欢迎大家交流学习(持续更新中)扫码关注我哦,我在这里↓↓↓
-
【摘要】 本帖简单介绍了审计日志的功能和查看审计日志的方法。数据库安全对数据库系统来说至关重要。GaussDB(DWS)将用户对数据库的所有操作写入审计日志。数据库安全管理员可以利用这些日志信息,重现导致数据库现状的一系列事件,找出非法操作的用户、时间和内容等。设置数据库审计可参考产品文档中设置数据库审计日志章节。建议用户在使用时合理配置审计项,对于一些数据敏感的业务和场景,强烈建议打开对表的DDL和DML审计。说明:本帖中涉及的数据和用户信息均为测试环境信息。1. 审计日志保存和转储目前,常用的审计日志保存方式为记录到表中和记录到OS文件中两种方式。但是表是数据库对象,如果采用记录到表中的方式,容易出现用户非法操作审计表的情况,审计记录的准确性难以保证,因此,从数据库安全角度出发,GaussDB(DWS)采用记录到OS文件的方式来保存审计结果,保证了审计结果的可靠性。由于审计日志会占用一定磁盘空间,为了防止本地文件过大,GaussDB(DWS)支持审计日志转储,具体方法可参考转储数据库审计日志章节。审计日志有两种保存策略,由参数audit_resource_policy控制:● on表示采用空间优先策略,最多存储audit_space_limit大小的日志。● off表示采用时间优先策略,最少存储audit_file_remain_time长度时间的日志。2. 审计日志查看首先要确保当前审计总开关audit_enabled和对应的审计项开关均已开启(表的DML操作审计由audit_dml_state控制,默认关闭,如需查看表上的dml操作,需提前打开该开关,同时,建议审计日志保留策略audit_resource_policy设置为on)。只有拥有AUDITADMIN属性的用户才可以查看审计记录,审计日志需通过数据库接口pg_query_audit和pgxc_query_audit查看。pg_query_audit可以查看当前CN的审计日志,pgxc_query_audit可以查看所有CN的审计日志,使用时一般用pgxc_query_audit接口查看审计。二者函数原型为:pg_query_audit(timestamptz startime,timestamptz endtime, audit_log)pgxc_query_audit(timestamptz startime,timestamptz endtime)其中,startime和endtime表示查看审计记录的开始时间和结束时间,满足审计条件的记录为startime ≤ 审计记录时间 < endtime;audit_log表示所查看的审计日志信息所在的物理文件路径,当不指定audit_log时,默认查看连接当前实例的审计日志信息。函数返回的字段如下:用户可以根据type类型或object_name对审计结果进行过滤,根据需要查看。常见的审计操作类型为:unknownlogin_successlogin_faileduser_logoutsystem_startsystem_stopsystem_recoversystem_switchlock_userunlock_usergrant_rolerevoke_roleuser_violationddl_databaseddl_directoryddl_tablespaceddl_schemaddl_userddl_tableddl_indexddl_viewddl_triggerddl_functionddl_resourcepoolddl_workloadddl_serverforhadoopddl_datasourceddl_nodegroupddl_rowlevelsecurityddl_synonymddl_typeddl_textsearchdml_actiondml_action_selectinternal_eventfunction_execcopy_tocopy_fromset_parameter3. 审计日志使用示例示例1:用户被锁,报错:FATAL: The account has been locked,如何查看用户被锁的原因:postgres=# select * from pgxc_query_audit('20201230 18:00:00',current_timestamp) where type = 'login_failed'; time | type | result | username | database | client_conninfo | object_name | detail_info | node_name | thread_id | local_port | remote_port ------------------------+--------------+--------+----------+----------+--------------------------+-------------+---------------------------------------------------------------+--------------+---------------------------------+------------+------------- 2020-12-30 18:59:07+08 | login_failed | failed | doubi | postgres | [unknown]@10.144.118.217 | postgres | login db(postgres)failed,authentication for user(doubi)failed | coordinator1 | 140508124395264@662641147918967 | 32000 | 49687 2020-12-30 18:59:11+08 | login_failed | failed | doubi | postgres | [unknown]@10.144.118.217 | postgres | login db(postgres)failed,authentication for user(doubi)failed | coordinator1 | 140508124395264@662641151174956 | 32000 | 49689 2020-12-30 18:59:13+08 | login_failed | failed | doubi | postgres | [unknown]@10.144.118.217 | postgres | login db(postgres)failed,authentication for user(doubi)failed | coordinator1 | 140508124395264@662641153871953 | 32000 | 49691 2020-12-30 18:59:16+08 | login_failed | failed | doubi | postgres | [unknown]@10.144.118.217 | postgres | login db(postgres)failed,authentication for user(doubi)failed | coordinator1 | 140508124395264@662641156887905 | 32000 | 49692 2020-12-30 18:59:20+08 | login_failed | failed | doubi | postgres | [unknown]@10.144.118.217 | postgres | login db(postgres)failed,authentication for user(doubi)failed | coordinator1 | 140508124395264@662641160061866 | 32000 | 49696 2020-12-30 18:59:23+08 | login_failed | failed | doubi | postgres | [unknown]@10.144.118.217 | postgres | login db(postgres)failed,authentication for user(doubi)failed | coordinator1 | 140508124395264@662641163187840 | 32000 | 49698 2020-12-30 18:59:25+08 | login_failed | failed | doubi | postgres | [unknown]@10.144.118.217 | postgres | login db(postgres)failed,authentication for user(doubi)failed | coordinator1 | 140508124395264@662641165671562 | 32000 | 49699 2020-12-30 18:59:28+08 | login_failed | failed | doubi | postgres | [unknown]@10.144.118.217 | postgres | login db(postgres)failed,authentication for user(doubi)failed | coordinator1 | 140508124395264@662641168137151 | 32000 | 49700 2020-12-30 18:59:31+08 | login_failed | failed | doubi | postgres | [unknown]@10.144.118.217 | postgres | login db(postgres)failed,authentication for user(doubi)failed | coordinator1 | 140508124395264@662641171124971 | 32000 | 49702 2020-12-30 18:59:33+08 | login_failed | failed | doubi | postgres | [unknown]@10.144.118.217 | postgres | login db(postgres)failed,authentication for user(doubi)failed | coordinator1 | 140508124395264@662641173650325 | 32000 | 49858 2020-12-30 18:59:36+08 | login_failed | failed | doubi | postgres | [unknown]@10.144.118.217 | postgres | login db(postgres)failed,the account(doubi)has been locked | coordinator1 | 140508124395264@662641176080044 | 32000 | 51402(11 rows)根据审计结果可以看到,IP为10.144.118.217的用户连续输入密码错误超过10次,导致doubi账户被锁。示例2:某张表数据为空,通过审计日志查看在该表上的操作(前提:已打开表的DML和DDL审计):postgres=# select * from pgxc_query_audit('20201230 19:15:00',current_timestamp) where object_name = 't1'; time | type | result | username | database | client_conninfo | object_name | detail_info | node_name | thread_id | local_port | remote_port ------------------------+------------+--------+----------+----------+----------------------------+-------------+-------------------------------------------------+--------------+---------------------------------+------------+------------- 2020-12-30 19:16:40+08 | dml_action | ok | dbadmin | postgres | Data Studio@10.144.118.217 | t1 | insert into t1 values (1,2) | coordinator1 | 140722584413952@662642200541821 | 32000 | 50437 2020-12-30 19:17:01+08 | dml_action | ok | dbadmin | postgres | Data Studio@10.144.118.217 | t1 | insert into t1 values (generate_series(1,10),2) | coordinator1 | 140722584413952@662642200541821 | 32000 | 50437 2020-12-30 19:17:11+08 | dml_action | ok | dbadmin | postgres | Data Studio@10.144.118.217 | t1 | delete from t1 | coordinator1 | 140722584413952@662642200541821 | 32000 | 50437(3 rows)通过审计日志可以看到,19:17:01 时刻,IP为10.144.118.217的用户通过Data Studio客户端向t1表中插入了数据,19:17:11 时该用户又对该表执行了delete操作导致数据为空。原文链接:https://bbs.huaweicloud.com/blogs/233104【推荐阅读】【最新活动汇总】DWS活动火热进行中,互动好礼送不停(持续更新中) HOT 【博文汇总】GaussDB(DWS)博文汇总1,欢迎大家交流探讨~(持续更新中)【维护宝典汇总】GaussDB(DWS)维护宝典汇总贴1,欢迎大家交流探讨(持续更新中)【项目实践汇总】GaussDB(DWS)项目实践汇总贴,欢迎大家交流探讨(持续更新中)【DevRun直播汇总】GaussDB(DWS)黑科技直播汇总,欢迎大家交流学习(持续更新中)【培训视频汇总】GaussDB(DWS) 培训视频汇总,欢迎大家交流学习(持续更新中)扫码关注我哦,我在这里↓↓↓
-
gaussdb的视图层级是能够通过SQL获取的,在参考https://bbs.huaweicloud.com/blogs/183594 这篇博文后,虽然能获取到视图层级,但在大集群中速度较慢。在项目实践中,因为有视图依赖,修改一个表定义需要删除上游视图,才能修改该表。因此需要快速获取一个表上游所有使用该表的视图的方法。以下方法经过实践,能在毫秒级获取一个表的所有引用的上游视图名称。sql如下,下面方法是一个表函数,可以取其中的循环语句作为日常使用的SQL:CREATE OR REPLACE FUNCTION public.gs_dependency_from_downtbl(input text,out downtbl text,out upview text,out depth int) RETURNS SETOF record LANGUAGE sql IMMUTABLE NOT FENCED SHIPPABLE AS $$ select downtbl::regclass::text,upview::regclass::text,depth from ( with recursive rec as ( select :input::regclass::oid as downtbl,:input::regclass::oid as upview,0 as depth --为了取oid类型,此处的其中一个字段是没有意义的。 union all select distinct a.refobjid as downtbl,b.refobjid as upview,depth + 1 as depth from pg_depend a,pg_depend b,rec where a.refclassid = 1259 AND a.classid=2618 AND b.deptype='i' AND a.objid=b.objid AND b.classid=2618 AND b.refclassid=1259 AND a.refobjid<>b.refobjid and a.refobjid = rec.upview ) select * from rec where depth > 0 ); $$ ;--查询t1表的所有上游视图 select * from gs_dependency_from_downtbl('public.t1');结果如下:类似地,可以通过一个视图,获取该视图下的所有对象(包括表和视图),函数SQL如下:CREATE OR REPLACE FUNCTION public.gs_dependency_from_upview(input text,out upview text,out downtbl text,out depth int) RETURNS SETOF record LANGUAGE sql IMMUTABLE NOT FENCED SHIPPABLE AS $$ select upview::regclass::text,downtbl::regclass::text,depth from ( with recursive rec as ( select :input::regclass::oid as upview,:input::regclass::oid as downtbl,0 as depth union all select distinct b.refobjid as upview,a.refobjid as downtbl,depth + 1 as depth from pg_depend a,pg_depend b,rec where a.refclassid = 1259 AND a.classid=2618 AND b.deptype='i' AND a.objid=b.objid AND b.classid=2618 AND b.refclassid=1259 AND a.refobjid<>b.refobjid and b.refobjid = rec.downtbl ) select * from rec where depth > 0 ); $$ ;--查询v8下的所有对象 select * from gs_dependency_from_upview('public.v8');
-
Gartner预测,2021年云数据库在整个数据库市场中的占比将首次达到50%;2023年75%的数据库将基于云的技术来构建并跑在云平台之上。 云数据库蓬勃发展的同时,云原生数据库的理念也被市场和各大云厂商所认可。云原生数据库,即基于统一的架构和云原生基础设施,实现多云协同、混合云解决方案、边云协同等能力的数据库。随着企业数字化进程进入到一个新阶段,企业上云不再是简单把业务放入容器和VM中,更应该让业务“生于云、长于云”,Service on Service,企业的数字化升级需要基于云数据库来构建。 云原生2.0是企业智能升级的新阶段,企业云化从“ON Cloud”走向“IN Cloud”,新生能力与既有能力有机协同、立而不破,实现资源高效、应用敏捷、业务智能、安全可信,成为“新云原生企业”。华为云GaussDB聚焦全场景,构筑云原生数据库全栈能力 云原生2.0时代下,企业对云数据库提出了生态兼容、事务一致、极致扩展、插件化等高诉求,华为云GaussDB整合多年数据库领域经验和客户诉求,聚焦全场景,构筑云原生数据库全栈能力,并参与制定云原生数据库行业标准,积极引领云原生数据库发展新方向。 华为云GaussDB构建的云原生数据库核心能力如下:(1)存算分离,极致弹性华为云GaussDB统一采用计算资源层与存储资源层解耦的技术架构,实现分钟级弹性伸缩、秒级高可用切换。(2)多平台软硬协同,数据存储可靠 华为云GaussDB支持ARM、x86等多种平台,并针对不同平台进行优化,充分发挥不同架构底座的硬件资源能力,确保全场景负载数据文件绝对可靠,并具备多副本强一致访问能力,故障自动恢复。(3)跨AZ/Region部署能力,让数据底座更加稳定可靠 华为云GaussDB具备跨AZ的部署能力,并且提供跨AZ的读一致性访问,多AZ节点必须读到一致的数据。此外还支持两地三中心、异地多活等能力。(4)统一架构,多模兼容,开放生态 华为云GaussDB积极拥抱并完全兼容业界主流的数据库生态如MySQL、Mongo和Redis,同时自主研发数据库引擎openGauss,单机代码开源,生态和能力开放,做真正符合客户需要的国产化数据产品。(5)智能运维,自动调度,让数据库运维更加高效、极简 华为云GaussDB积极利用AI技术实现数据库自调优、自诊断、自安全、自运维、自愈等能力,协助DBA降低运维难度,提升运维效率,自动调度平衡资源池。华为云GaussDB坚持长期战略投入,打造世界级数据库服务 近期,中央国家机关2021年数据库软件协议供货采购项目征集公告发布,在央采一期传统的纯软件采购项目中,华为因主要聚焦云数据库赛道,并没有参与这一次一期的纯软交付的央采项目,但华为非常鼓励伙伴基于openGauss开放的能力打造他们自有品牌的数据库商业发行版并积极参与类似这次的央采一期项目;同时华为基于云数据库的能力优势,未来将重点参与相关方向的各类数据库竞标活动。 数据库作为IT产业的三大根技术之一,专家投入的深度、资源投入的决心以及对于数据库领域的专注和执着缺一不可。华为坚持长期战略投入,并汲取世界各地7大研究所不同领域超过100+的业界顶级专家,近1000+数据库领域相关的专业人才,有着强大的专家团和研发团队做支撑。同时立足华为云原生全栈能力,整合华为公司在多元算力、整机服务器、高速存储、新一代网络及企业级软件等领域的经验,基于统一的DFV分布式存储架构与RDMA高速网络等底层硬件的积累和软硬协同,打造了稳定可靠、极致性能的数据库服务。 展望未来,华为公司有能力、有信心在数据库和数据赛道传承华为优良传统,打造以“解决客户实际问题”的世界顶级产品,并在面向未来的云原生数据库方向不断投入,帮助客户快而好的完成“云原生数字化转型”,实现企业智能升级。同时,华为公司秉承“生态开放、互惠互利”的原则,打造基于合作伙伴+客户+开发者共赢的数据库生态圈,旨在做大做强国产数据库事业。 Ps:云数据库开年采购季活动火热进行中,爆款云数据库2.7折起,新购满额还送华为手机P40 Pro 5G,戳此直达>> https://activity.huaweicloud.com/dbs_Promotion/index.html
-
【摘要】 本帖简单介绍GaussDB(DWS)常用视图和使用方式。背景:使用数据库过程中,执行一条查询语句很慢,想知道后台语句的执行情况。可通过以下方式查看数据库后台当前执行的所有语句和语句的执行情况。1. PGXC_STAT_ACTIVITY视图介绍PGXC_STAT_ACTIVITY视图显示当前集群下所有CN的查询相关的信息,只有系统管理员才有权限执行。该视图的coorname表示执行该语句的CN,query_id字段表示该query的唯一ID,同一条语句在不同节点的query_id相同,不同语句的query_id不同。pid表示该语句在对应节点上的线程ID,usename表示执行该语句的用户,query_start表示该语句开始执行的时间,enqueue表示语句是否正在排队。该字段为空表示未处于排队状态,state字段表示对应的语句执行状态,常见状态如下:active:后端正在执行一个查询。idle:后端正在等待一个新的客户端命令。idle in transaction:后端在事务中,但事务中没有语句在执行。idle in transaction (aborted):后端在事务中,但事务中有语句执行失败。利用此视图对相关字段进行过滤,即可查询得到当前的后台所有CN上的活跃语句:select coorname, usename, client_addr, sysdate-query_start as dur, enqueue, query_id, substr(query,1,60)from pgxc_stat_activity where usename != 'Ruby' and state != 'idle' order by dur desc;其中,Ruby用户为数据库的初始用户,一般情况下我们不关心初始用户相关的语句。执行上述查询即可得到当前后台所有活跃的sql情况和已经执行的时长。接下来,可以根据查到的query_id利用等待视图PGXC_THREAD_WAIT_STATUS对执行的慢sql进行分析,查看语句的执行状态。2. PGXC_THREAD_WAIT_STATUS视图介绍通过CN节点查看PGXC_THREAD_WAIT_STATUS视图,可以查看集群全局各个节点上所有SQL语句产生的线程之间的调用层次关系,以及各个线程的阻塞等待状态,从而更容易定位进程停止响应问题以及类似现象的原因。该视图中我们需重点关注wait_status字段和wait_event字段,其中,wait_status字段表示当前线程的等待状态,wait_event表示等待事件,一般为acquire lock、acquire lwlock、wait io三种类型。根据上一步查询得到的query_id查询等待视图,即可得到该语句的等待时间状态,分析出慢sql的瓶颈点:select * from pgxc_thread_wait_status where query_id = 20971544;例如:select * from pgxc_thread_wait_status where query_id=20971544; node_name | db_name | thread_name | query_id | tid | lwtid | ptid | tlevel | smpid | wait_status | wait_event --------------+----------+--------------+----------+-----------------+-------+-------+--------+-------+---------------------- datanode1 | postgres | coordinator1 | 20971544 | 139902867994384 | 22735 | | 0 | 0 | wait node: datanode3 | datanode1 | postgres | coordinator1 | 20971544 | 139902838634256 | 22970 | 22735 | 5 | 0 | synchronize quit | datanode1 | postgres | coordinator1 | 20971544 | 139902607947536 | 22972 | 22735 | 5 | 1 | synchronize quit | datanode2 | postgres | coordinator1 | 20971544 | 140632156796688 | 22736 | | 0 | 0 | wait node: datanode3 | datanode2 | postgres | coordinator1 | 20971544 | 140632030967568 | 22974 | 22736 | 5 | 0 | synchronize quit | datanode2 | postgres | coordinator1 | 20971544 | 140632081299216 | 22975 | 22736 | 5 | 1 | synchronize quit | datanode3 | postgres | coordinator1 | 20971544 | 140323627988752 | 22737 | | 0 | 0 | wait node: datanode3 | datanode3 | postgres | coordinator1 | 20971544 | 140323523131152 | 22976 | 22737 | 5 | 0 | net flush data | datanode3 | postgres | coordinator1 | 20971544 | 140323548296976 | 22978 | 22737 | 5 | 1 | net flush data datanode4 | postgres | coordinator1 | 20971544 | 140103024375568 | 22738 | | 0 | 0 | wait node: datanode3 datanode4 | postgres | coordinator1 | 20971544 | 140102919517968 | 22979 | 22738 | 5 | 0 | synchronize quit | datanode4 | postgres | coordinator1 | 20971544 | 140102969849616 | 22980 | 22738 | 5 | 1 | synchronize quit | coordinator1 | postgres | gsql | 20971544 | 140274089064208 | 22579 | | 0 | 0 | wait node: datanode4 |(13 rows)可以看到,该语句在CN1执行,coordinator1在等datanode4,datanode4在等datanode3,datanode3在的等待状态为net flush data,表示该节点正在向网络中发送数据,说明整个查询的瓶颈点在datanode3的网络传输,该节点可能存在网络瓶颈。等待视图中各等待状态详情可以通过以下文档查看:https://support.huaweicloud.com/devg-dws/dws_04_0565.html3. 二者结合使用对于一些有明显特征的SQL,比如表名/别名/注释等,能根据该特征标志出唯一sql,可以执行以下SQL将PGXC_STAT_ACTIVITY和PGXC_THREAD_WAIT_STATUS进行关联查询:select w.* from pgxc_thread_wait_status w left join pgxc_stat_activity a on w.query_id=a.query_id where a.query_id != 0and a.query like '%explain performance%'and a.query not like '%pgxc_stat_activity%';本例中,explain performance能够标识唯一SQL,即可使用该sql直接查询得到等待视图情况。原文链接:https://bbs.huaweicloud.com/blogs/231261【推荐阅读】【最新活动汇总】DWS活动火热进行中,互动好礼送不停(持续更新中) HOT 【博文汇总】GaussDB(DWS)博文汇总1,欢迎大家交流探讨~(持续更新中)【维护宝典汇总】GaussDB(DWS)维护宝典汇总贴1,欢迎大家交流探讨(持续更新中)【项目实践汇总】GaussDB(DWS)项目实践汇总贴,欢迎大家交流探讨(持续更新中)【DevRun直播汇总】GaussDB(DWS)黑科技直播汇总,欢迎大家交流学习(持续更新中)【培训视频汇总】GaussDB(DWS) 培训视频汇总,欢迎大家交流学习(持续更新中)扫码关注我哦,我在这里↓↓↓
-
【摘要】 查询表相关主键约束、唯一约束或者唯一索引。SELECT n.nspname AS schemaname, --schema名称 c1.relname AS tablename, -- 表名 c2.relname AS indexname, -- 索引名称 s.conname AS conname, -- 约束名称 pg_get_constraintdef(s.oid) AS constraintdef, -- 如果是约束,输出约束定义 CASE WHEN s.conname IS NULL THEN pg_get_indexdef(x.indexrelid) END AS indexdef -- 如果不是约束,输出索引定义FROM pg_index xINNER JOIN pg_class c1 ON c1.oid = x.indrelidINNER JOIN pg_class c2 ON c2.oid = x.indexrelidINNER JOIN pg_namespace n ON n.oid = c1.relnamespaceLEFT JOIN pg_constraint s ON s.conrelid = x.indrelid AND s.conindid = x.indexrelidWHERE (x.indisprimary = true OR x.indisunique = true)AND c1.relkind = 'r' AND x.indrelid >= 16384 AND x.indexrelid > 16384AND (c1.reloptions IS NULL OR c1.reloptions::text not like '%internal_mask%') -- 排除内置对象ORDER BY schemaname, tablename, indexname;原文链接:https://bbs.huaweicloud.com/blogs/230137【推荐阅读】【最新活动汇总】DWS活动火热进行中,互动好礼送不停(持续更新中) HOT 【博文汇总】GaussDB(DWS)博文汇总1,欢迎大家交流探讨~(持续更新中)【维护宝典汇总】GaussDB(DWS)维护宝典汇总贴1,欢迎大家交流探讨(持续更新中)【项目实践汇总】GaussDB(DWS)项目实践汇总贴,欢迎大家交流探讨(持续更新中)【DevRun直播汇总】GaussDB(DWS)黑科技直播汇总,欢迎大家交流学习(持续更新中)【培训视频汇总】GaussDB(DWS) 培训视频汇总,欢迎大家交流学习(持续更新中)扫码关注我哦,我在这里↓↓↓
-
【摘要】 实际业务中,我们可能会遇到数据库系统 hang 住的问题,分布式死锁是数据库系统 hang 问题的一个主要原因。本文重点介绍如何通过 SQL 语句,对分布式死锁进行检测和恢复。分布式数仓应用场景中,我们经常遇到数据库系统 hang 住的问题,所谓 hang 是指虽然数据库系统还在运行,但部分或全部业务无法正常执行。hang 问题的原因有很多,其中以分布式死锁最为常见,本次主要分享在碰到分布式死锁时,如何快速地解决死锁问题。GaussDB(DWS) 作为分布式数仓,通过锁机制来实行并发控制,因此也存在产生分布式死锁的可能。虽然分布式死锁无法避免,但幸运的是其提供了多种系统视图,能够保证在分布式死锁发生之后,快速地对死锁进行定位。本文主要介绍了在 GaussDB(DWS) 中,如何通过 SQL 语句,对分布式死锁进行检测和恢复。本文介绍的方法大致分为 4 步:1. 收集各节点的锁信息。2. 构建等待关系。3. 检测循环等待。4. 中止事务以消除死锁。本文介绍的方法使用简单,门槛低,可以确保在分布式死锁发生之后,快速解决问题,恢复业务。通过 SQL 语句进行分布式死锁的检测与消除分布式死锁和单节点死锁的比较单节点死锁单节点死锁是指,死锁中的所有锁等待信息来自同一个节点,例如:-- 事务 transaction1-- 所在节点:CN1BEGIN;TRUNCATE t1;EXECUTE DIRECT ON(DN1) 'SELECT * FROM t2';COMMIT;-- 事务 transaction2-- 所在节点:CN1BEGIN;TRUNCATE t2;EXECUTE DIRECT ON(DN2) 'SELECT * FROM t1';COMMIT;假设上述两个事务的执行顺序如下:1. [transaction1] TRUNCATE t12. [transaction2] TRUNCATE t23. [transaction1] EXECUTE DIRECT ON(DN1) 'SELECT * FROM t2'4. [transaction2] EXECUTE DIRECT ON(DN2) 'SELECT * FROM t1'该执行顺序会导致死锁的产生。由于事务 transaction1 和 transaction2 都在 CN1 上执行,死锁中的所有锁等待信息都在 CN1 上,因此该死锁为单节点死锁。节点持有锁等待锁CN1[transaction1] TRUNCATE t1[transaction2] EXECUTE DIRECT ON(DN1) 'SELECT * FROM t2'CN1[transaction2] TRUNCATE t2[transaction1] EXECUTE DIRECT ON(DN2) 'SELECT * FROM t1'GaussDB(DWS) 支持自动处理单节点死锁。当某个节点上的多个事务陷入循环等待时,数据库系统会自动将其中一个事务中止,从而消除死锁。分布式死锁分布式死锁是指,死锁中的锁等待信息来自不同节点。例如:-- 事务 transaction1-- 所在节点:CN1BEGIN;TRUNCATE t1;EXECUTE DIRECT ON(DN1) 'SELECT * FROM t2';COMMIT;-- 事务 transaction2-- 所在节点:CN2BEGIN;TRUNCATE t2;EXECUTE DIRECT ON(DN2) 'SELECT * FROM t1';COMMIT;本例与上一节中的例子相比,只有事务 transaction2 的所在节点从 CN1 改为了 CN2。假设两个事务的执行顺序和上一节中的执行顺序一致,还是会产生死锁,死锁中的锁等待信息如下:节点持有锁等待锁CN1[transaction1] TRUNCATE t1[transaction2] EXECUTE DIRECT ON(DN1) 'SELECT * FROM t2'CN2[transaction1] TRUNCATE t2[transaction1] EXECUTE DIRECT ON(DN2) 'SELECT * FROM t1'这就是一个典型的分布式死锁,单独看 CN1 或 CN2 上的锁等待信息,都看不出来有死锁,但将多个节点的锁等待信息放到一起看,就能找到有循环等待的现象。发生分布式死锁时,陷入死锁的事务全部都无法继续执行下去,只有其中一个事务锁等待超时,剩余事务才能继续执行。默认情况下,锁等待超时时间是 20 分钟。分布式死锁的检测与消除当我们观察到数据库系统出现 hang 问题时,我们需要通过 SQL 语句检测分布式死锁,如果发现确实存在分布式死锁,还需要对死锁进行消除。接下来以之前的分布式死锁为例,介绍分布式死锁的检测和消除的方法。收集各节点的锁信息为了检测分布式死锁,首先需要获得各节点的锁信息。GaussDB(DWS) 中可以通过 PG_LOCKS 视图查询当前节点的锁信息,因此可以通过 EXECUTE DIRECT 语句在所有节点查询 PG_LOCKS 视图,并收集到当前节点中。注意此处有一个细节,PG_LOCKS 视图中,很多信息是以 OID 类型给出的,例如一个锁加在一个表上,PG_LOCKS 视图会给出表的 OID。由于同一个表在各节点中的 OID 不一定相同,因此不能通过 OID 来标识一个表。在收集锁信息时,需要先将表的 OID 转换成 SCHEMA 名加表名。其它 OID 信息例如分区 OID 等也同理,需要转化为对应的名字。执行附件中的示例代码 pgxc_locks.sql,就可以收集到各节点的锁信息: locktype | nodename | datname | usename | nspname | relname | partname | page | tuple | virtualxid | transactionid | virtualtransaction | mode | granted | client_addr | application_name | pid | xact_start | query_start | state | query_id | query---------------+--------------+----------+---------+---------+---------+----------+------+-------+------------+---------------+--------------------+---------------------+---------+-------------+------------------+-----------------+----------------------------+----------------------------+---------------------+-------------------+----------------------------------------------------- virtualxid | cn_5002 | postgres | tyx_1 | | | | | | 12/94 | | 12/94 | ExclusiveLock | t | | gsql | 140110481323776 | 2020-12-25 17:18:54.238933 | 2020-12-25 17:19:37.715447 | active | 0 | EXECUTE DIRECT ON(dn_6003_6004) 'SELECT * FROM t1'; virtualxid | cn_5002 | postgres | tyx_1 | | | | | | 9/298 | | 9/298 | ExclusiveLock | t | ::1/128 | cn_5001 | 140110672164608 | 2020-12-25 17:18:40.478704 | 2020-12-25 17:18:40.479682 | idle in transaction | 0 | TRUNCATE t1; virtualxid | cn_5002 | postgres | tyx_1 | | | | | | 6/161 | | 6/161 | ExclusiveLock | t | | WLMArbiter | 140110762325760 | 2020-12-25 17:20:18.613815 | 2020-12-25 16:53:35.027585 | active | 0 | WLM arbiter sync info by CCN and CNs virtualxid | cn_5002 | postgres | tyx_1 | | | | | | 5/162 | | 5/162 | ExclusiveLock | t | | WorkloadMonitor | 140110779119360 | 2020-12-25 17:20:27.16458 | 2020-12-25 16:53:35.027217 | active | 0 | WLM monitor update and verify local info virtualxid | cn_5002 | postgres | tyx_1 | | | | | | 3/325 | | 3/325 | ExclusiveLock | t | | workload | 140110846744320 | 2020-12-25 17:20:25.372654 | 2020-12-25 16:53:35.02741 | active | 72339069014641297 | WLM fetch collect info from data nodes advisory | cn_5002 | postgres | tyx_1 | | | | | | | | 12/94 | ShareLock | t | | gsql | 140110481323776 | 2020-12-25 17:18:54.238933 | 2020-12-25 17:19:37.715447 | active | 0 | EXECUTE DIRECT ON(dn_6003_6004) 'SELECT * FROM t1'; relation | cn_5002 | postgres | tyx_1 | public | t1 | | | | | | 9/298 | AccessExclusiveLock | t | ::1/128 | cn_5001 | 140110672164608 | 2020-12-25 17:18:40.478704 | 2020-12-25 17:18:40.479682 | idle in transaction | 0 | TRUNCATE t1; relation | cn_5002 | postgres | tyx_1 | public | t1 | | | | | | 12/94 | AccessShareLock | f | | gsql | 140110481323776 | 2020-12-25 17:18:54.238933 | 2020-12-25 17:19:37.715447 | active | 0 | EXECUTE DIRECT ON(dn_6003_6004) 'SELECT * FROM t1'; transactionid | cn_5002 | postgres | tyx_1 | | | | | | | 10269 | 12/94 | ExclusiveLock | t | | gsql | 140110481323776 | 2020-12-25 17:18:54.238933 | 2020-12-25 17:19:37.715447 | active | 0 | EXECUTE DIRECT ON(dn_6003_6004) 'SELECT * FROM t1'; transactionid | cn_5002 | postgres | tyx_1 | | | | | | | 10266 | 9/298 | ExclusiveLock | t | ::1/128 | cn_5001 | 140110672164608 | 2020-12-25 17:18:40.478704 | 2020-12-25 17:18:40.479682 | idle in transaction | 0 | TRUNCATE t1; relation | cn_5002 | postgres | tyx_1 | public | t2 | | | | | | 12/94 | AccessExclusiveLock | t | | gsql | 140110481323776 | 2020-12-25 17:18:54.238933 | 2020-12-25 17:19:37.715447 | active | 0 | EXECUTE DIRECT ON(dn_6003_6004) 'SELECT * FROM t1'; virtualxid | dn_6001_6002 | postgres | tyx_1 | | | | | | 17/433 | | 17/433 | ExclusiveLock | t | ::1/128 | cn_5001 | 140552375822080 | 2020-12-25 17:18:40.478704 | 2020-12-25 17:18:50.513948 | idle in transaction | 0 | TRUNCATE t1; virtualxid | dn_6001_6002 | postgres | tyx_1 | | | | | | 23/692 | | 23/692 | ExclusiveLock | t | ::1/128 | cn_5002 | 140552359040768 | 2020-12-25 17:18:54.238933 | 2020-12-25 17:18:56.830053 | idle in transaction | 0 | TRUNCATE t2; virtualxid | dn_6001_6002 | postgres | tyx_1 | | | | | | 2/1607 | | 2/1607 | ExclusiveLock | t | | workload | 140552945264384 | | 2020-12-25 16:53:35.041283 | active | 0 | WLM fetch collect info from data nodes transactionid | dn_6001_6002 | postgres | tyx_1 | | | | | | | 10266 | 17/433 | ExclusiveLock | t | ::1/128 | cn_5001 | 140552375822080 | 2020-12-25 17:18:40.478704 | 2020-12-25 17:18:50.513948 | idle in transaction | 0 | TRUNCATE t1; relation | dn_6001_6002 | postgres | tyx_1 | | | | | | | | 23/692 | AccessExclusiveLock | t | ::1/128 | cn_5002 | 140552359040768 | 2020-12-25 17:18:54.238933 | 2020-12-25 17:18:56.830053 | idle in transaction | 0 | TRUNCATE t2; relation | dn_6001_6002 | postgres | tyx_1 | | | | | | | | 17/433 | AccessExclusiveLock | t | ::1/128 | cn_5001 | 140552375822080 | 2020-12-25 17:18:40.478704 | 2020-12-25 17:18:50.513948 | idle in transaction | 0 | TRUNCATE t1; relation | dn_6001_6002 | postgres | tyx_1 | public | t2 | | | | | | 23/692 | ShareLock | t | ::1/128 | cn_5002 | 140552359040768 | 2020-12-25 17:18:54.238933 | 2020-12-25 17:18:56.830053 | idle in transaction | 0 | TRUNCATE t2; relation | dn_6001_6002 | postgres | tyx_1 | public | t2 | | | | | | 23/692 | AccessExclusiveLock | t | ::1/128 | cn_5002 | 140552359040768 | 2020-12-25 17:18:54.238933 | 2020-12-25 17:18:56.830053 | idle in transaction | 0 | TRUNCATE t2;省略若干行(55 rows)构建等待关系收集到各节点的锁信息之后,就可以开始构建等待关系了。事务 A 等待事务 B,需要满足 3 个条件:1. 两个事务加锁的资源相同(同一个表、同一个分区、同一个页面或同一个元组等)。特别注意,如果事务 A 对 DN1 的 t1 表的加锁,事务 B 对 DN2 的 t1 表的加锁,则我们认为它们加锁的资源不同,只有同一节点上的同一资源才被认为是相同的资源。2. 事务 B 已经持有锁,而事务 A 还未持有锁。3. 事务 A 和事务 B 申请的锁的级别互斥。通过对上一步收集到的锁信息进行处理,就可以构建出事务的等待关系。执行附件中的示例代码 pgxc_locks_wait.sql,就可以获得等待关系: locktype | nodename | datname | acquire_lock_pid | hold_lock_pid | acquire_lock_event | hold_lock_event----------+----------+----------+------------------+-----------------+-------------------------------------------------------------------------+-------------------------------------------------------- relation | cn_5001 | postgres | 140508814374656 | 140508792350464 | usename : tyx_1 +| usename : tyx_1 + | | | | | nspname : public +| nspname : public + | | | | | relname : t2 +| relname : t2 + | | | | | partname : +| partname : + | | | | | page : +| page : + | | | | | tuple : +| tuple : + | | | | | virtualxid : +| virtualxid : + | | | | | transactionid : +| transactionid : + | | | | | virtualtransaction: 11/13 +| virtualtransaction: 12/1323 + | | | | | mode : AccessShareLock +| mode : AccessExclusiveLock + | | | | | client_addr : +| client_addr : ::1/128 + | | | | | application_name : gsql +| application_name : cn_5002 + | | | | | xact_start : 2020-12-25 17:18:40.478704 +| xact_start : 2020-12-25 17:18:54.238933 + | | | | | query_start : 2020-12-25 17:19:23.0923 +| query_start : 2020-12-25 17:18:54.239319 + | | | | | state : active +| state : idle in transaction + | | | | | query_id : 0 +| query_id : 0 + | | | | | query : EXECUTE DIRECT ON(dn_6001_6002) 'SELECT * FROM t2';+| query : TRUNCATE t2; + | | | | | ------------------------------------------------------ | ------------------------------------------------------ relation | cn_5002 | postgres | 140110481323776 | 140110672164608 | usename : tyx_1 +| usename : tyx_1 + | | | | | nspname : public +| nspname : public + | | | | | relname : t1 +| relname : t1 + | | | | | partname : +| partname : + | | | | | page : +| page : + | | | | | tuple : +| tuple : + | | | | | virtualxid : +| virtualxid : + | | | | | transactionid : +| transactionid : + | | | | | virtualtransaction: 12/94 +| virtualtransaction: 9/298 + | | | | | mode : AccessShareLock +| mode : AccessExclusiveLock + | | | | | client_addr : +| client_addr : ::1/128 + | | | | | application_name : gsql +| application_name : cn_5001 + | | | | | xact_start : 2020-12-25 17:18:54.238933 +| xact_start : 2020-12-25 17:18:40.478704 + | | | | | query_start : 2020-12-25 17:19:37.715447 +| query_start : 2020-12-25 17:18:40.479682 + | | | | | state : active +| state : idle in transaction + | | | | | query_id : 0 +| query_id : 0 + | | | | | query : EXECUTE DIRECT ON(dn_6003_6004) 'SELECT * FROM t1';+| query : TRUNCATE t1; + | | | | | ------------------------------------------------------ | ------------------------------------------------------(2 rows)等待关系判环构建出事务的等待关系之后,就可以通过检查等待关系是否成环,来判断当前是否有分布式死锁。一般情况下,等待关系不会太多,通过观察就可以判断出当前有无分布式死锁。通过观察上一节中构建的等待信息,可以很容易地判断出事务 transaction1 和 transaction2 发生了循环等待,即产生了死锁。消除死锁上一步最终可能会找到等待关系中的一个或多个环,对于每个环,需要中止环中的一个事务,才能消除死锁。至于应该选择环中的哪个事务进行中止,需要我们从事务的重要性、已执行时间等多方面进行考虑,最终选择一个对业务影响最小的事务进行中止。总结通过 SQL 语句,我们可以很方便地处理分布式死锁。当我们在实际业务中遇到数据库系统 hang 住的问题时,可以借助本文提供的方法,检查 hang 问题是否是分布式死锁引起的,如果问题确实是由分布式死锁引起的,还可以通过中止某个陷入死锁的事务,来快速恢复业务。原文链接:https://bbs.huaweicloud.com/blogs/228840【推荐阅读】【最新活动汇总】DWS活动火热进行中,互动好礼送不停(持续更新中) HOT 【博文汇总】GaussDB(DWS)博文汇总1,欢迎大家交流探讨~(持续更新中)【维护宝典汇总】GaussDB(DWS)维护宝典汇总贴1,欢迎大家交流探讨(持续更新中)【项目实践汇总】GaussDB(DWS)项目实践汇总贴,欢迎大家交流探讨(持续更新中)【DevRun直播汇总】GaussDB(DWS)黑科技直播汇总,欢迎大家交流学习(持续更新中)【培训视频汇总】GaussDB(DWS) 培训视频汇总,欢迎大家交流学习(持续更新中)扫码关注我哦,我在这里↓↓↓
-
【摘要】 在日常数据库使用中,经常会遇到UUID这种数据类型,此次博文主要向大家分享一下UUID的基本概念及如何在华为云数仓GaussDB(DWS)中生成UUID。前言在日常数据库使用中,经常会遇到UUID这种数据类型,此次博文主要向大家分享一下UUID的基本概念及如何在华为云数仓GaussDB(DWS)中生成UUID。1. UUID的定义UUID含义是通用唯一识别码 (Universally Unique Identifier),这是一个软件建构的标准,也是被开源软件基金会 (Open Software Foundation, OSF) 组织应用在分布式计算环境 (Distributed Computing Environment, DCE) 领域的重要部分。其目的是让分布式系统中的所有元素都能有唯一的辨识信息,而不需要通过中央控制端来做辨识信息的指定。如此一来,每个人都可以创建不与其它人冲突的UUID。在这样的情况下,就不需考虑数据库创建时的名称重复问题。目前最广泛应用的UUID,是微软公司的全局唯一标识符(GUID),而其他重要的应用,则有Linux ext2/ext3文件系统、LUKS加密分区、GNOME、KDE、Mac OS X等等。2. UUID的格式UUID由开放软件基金会标准化,作为分布式计算环境的一部分,在互联网工程任务组(IETF)公布的RFC 4122标准中对UUID进行了标准化。标准的UUID由36个字符组成,其中包括32个16进制数字和4个连字分隔符‘-’,形式为8-4-4-4-12,标准的UUID示例如下:a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11GaussDB(DWS)同样支持以其他方式输入:大写字母和数字、由花括号包围的标准格式、省略部分或所有连字符、在任意一组四位数字之后加一个连字符,示例如下:A0EEBC99-9C0B-4EF8-BB6D-6BB9BD380A11{a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11}a0eebc999c0b4ef8bb6d6bb9bd380a11 a0ee-bc99-9c0b-4ef8-bb6d-6bb9-bd38-0a11{a0eebc99-9c0b4ef8-bb6d6bb9-bd380a11}3. UUID的组成UUID采用时间信息和空间信息确保全局唯一,通常由时间戳信息、时钟序列和节点ID(MAC地址)组成。而GaussDB(DWS)分布式集群中多个节点可能部署在同一个机器上,其MAC地址相同,UUID存在冲突的风险。因此GaussDB(DWS)将最后48bit为的MAC地址替换为生成UUID的CN或DN的序号和当前的线程ID,确保UUID在分布式集群内部做到全局唯一,其组成如下图所示:4. 生成UUIDGaussDB(DWS)提供接口函数uuid_generate_v1生成一个UUID类型的的序列号,示例如下:SELECT uuid_generate_v1(); uuid_generate_v1-------------------------------------- 5fe5aaf3-076a-0279-6049-c927e700fffe(1 row)注意:uuid_generate_v1函数根据时间信息、集群节点编号、生成该序列的线程号和时钟序列生成UUID,可以确保在单个集群内部全局唯一,但在多个集群间时间信息、集群节点编号、线程号和时钟序列仍然存在同时相等的可能性,因此多个集群间生成的UUID存在极低概率冲突的可能性。GaussDB(DWS)提供兼容Oracle的sys_guid函数,生成Oracle的类似UUID的GUID序列,示例如下:SELECT sys_guid(); sys_guid---------------------------------- 5FE5ADAF0D3109BF2AB7C927E700FFFE(1 row)注意:sys_guid函数内部实现原理同uuid_generate_v1函数,因此多个集群间生成的GUID同样存在极低概率冲突的可能性。5. UUID的应用UUID全局唯一的特点,可以作为数据表生成主键,也可以作为数据表的分布列,uuid_generate_v1作为数据表分布列的默认值时,通过Hash分布可以将数据均匀分布到各个DN上,防止数据倾斜。示例如下:--int类型作为分布列 testDB=# CREATE TABLE tt01(a INT, b INT) DISTRIBUTE BY hash(a);CREATE TABLEtestDB=# INSERT INTO tt01 VALUES(1, 10);INSERT 0 1testDB=# INSERT INTO tt01 VALUES(1, 10);INSERT 0 1testDB=# INSERT INTO tt01 VALUES(1, 10);INSERT 0 1testDB=# INSERT INTO tt01 VALUES(1, 10);INSERT 0 1testDB=# INSERT INTO tt01 VALUES(1, 10);INSERT 0 1testDB=# SELECT * FROM tt01; a | b---+---- 1 | 10 1 | 10 1 | 10 1 | 10 1 | 10(5 rows)testDB=# SELECT table_skewness('tt01'); table_skewness------------------------------------- ("datanode1 ",5,100.000%) ("datanode2 ",0,0.000%)(2 rows)--UUID类型作为分布列 testDB=# CREATE TABLE tt02 (id UUID default uuid_generate_v1(), a INT, b INT) DISTRIBUTE BY hash(id);CREATE TABLEtestDB=# INSERT INTO tt02(a, b) VALUES(1, 10);INSERT 0 1testDB=# INSERT INTO tt02(a, b) VALUES(1, 10);INSERT 0 1testDB=# INSERT INTO tt02(a, b) VALUES(1, 10);INSERT 0 1testDB=# INSERT INTO tt02(a, b) VALUES(1, 10);INSERT 0 1testDB=# INSERT INTO tt02(a, b) VALUES(1, 10);INSERT 0 1 testDB=# SELECT * FROM tt02; id | a | b--------------------------------------+---+---- 5fe5b85c-92a6-09c3-3690-f42fd700fffe | 1 | 10 5fe5b85c-e7e4-098b-3693-f42fd700fffe | 1 | 10 5fe5b85c-051c-0a77-3694-f42fd700fffe | 1 | 10 5fe5b85c-b09c-09fa-3691-f42fd700fffe | 1 | 10 5fe5b85c-ce27-0941-3692-f42fd700fffe | 1 | 10(5 rows)testDB=# SELECT table_skewness('tt02'); table_skewness------------------------------------ ("datanode1 ",3,60.000%) ("datanode2 ",2,40.000%)(2 rows)6. 总结UUID的显著优点就是全局唯一,不需要中心节点,单个节点独立生成,程序在不同的数据库中迁移时效果不受影响。缺点也很显著,UUID比INT占用更多的存储空间,索引效率低,生成的ID很随机,没有递增的特性,同时辨识困难。因此,在应用中,要根据实际情况选择UUID还是Sequence作为数据表主键。原文链接:https://bbs.huaweicloud.com/blogs/228838【推荐阅读】【最新活动汇总】DWS活动火热进行中,互动好礼送不停(持续更新中) HOT 【博文汇总】GaussDB(DWS)博文汇总1,欢迎大家交流探讨~(持续更新中)【维护宝典汇总】GaussDB(DWS)维护宝典汇总贴1,欢迎大家交流探讨(持续更新中)【项目实践汇总】GaussDB(DWS)项目实践汇总贴,欢迎大家交流探讨(持续更新中)【DevRun直播汇总】GaussDB(DWS)黑科技直播汇总,欢迎大家交流学习(持续更新中)【培训视频汇总】GaussDB(DWS) 培训视频汇总,欢迎大家交流学习(持续更新中)扫码关注我哦,我在这里↓↓↓
-
一,表锁GaussDB(DWS) 支持的表锁级别很多,从最低的1级到最高的8级:1级锁,AccessShareLockSELECT语句申请AccessShareLock,只与8级锁冲突,只会阻塞DDL等语句。2级锁,RowShareLockSELECT FOR SHARE/UPDATE语句申请RowShareLock,与7/8级锁冲突。3级锁,RowExclusiveLockINSERT/UPDATE/DELET语句申请RowExclusiveLock,与6-8级锁冲突。4级锁,ShareUpdateExclusiveLockVACUUM/ANALYZE语句申请ShareUpdateExclusiveLock,与5-8级锁冲突。5级锁,ShareLockCREATE INDEX语句申请ShareLock,与4/6/7/8级锁冲突,与5级锁不冲突,同一个表的多个CREATE INDEX可以同时执行不阻塞。6级锁,ShareRowExclusiveLock在GaussDB(DWS) 中,ShareRowExclusiveLock目前只在ALTER SEQUENCE中用到,阻塞表的增删改以及更高级别操作,该锁与3-8级锁冲突。7级锁,ExclusiveLockVACUUM FULL,MERGE PARTITION等语句申请ExclusiveLock级锁,ExclusiveLock只与SELECT兼容,与2-8级锁冲突。除了表锁外,事务锁,扩展锁、记录锁都是使用的ExclusiveLock,下面会进行详细介绍。8级锁,AccessExclusiveLockDDL等语句会申请AccessExclusiveLock,包括ALTER TABLE,DROP TABLE,TRUNCATE,REINDEX,VACUUM FULL等,8级锁与所有锁都冲突。锁冲突矩阵详细的锁冲突矩阵图如下所示: LOCK [TABLE]表锁还可以手动的使用SQL语句的方式进行强制上锁,SQL语句的格式如下所示:LOCK [ TABLE ] [ ONLY ] name [ * ] [, ...] [ IN lockmode MODE ] [ NOWAIT ]其中 lockmode 可以是以下之一: ACCESS SHARE | ROW SHARE | ROW EXCLUSIVE | SHARE UPDATE EXCLUSIVE | SHARE | SHARE ROW EXCLUSIVE | EXCLUSIVE | ACCESS EXCLUSIVE要注意的是LOCK语句只能在事务块中执行,事务结束会释放。二,其他锁除了表锁,GaussDB(DWS) 中还有很多其他的锁,下面列出一些常用的锁:1,事务锁写事务会获取一个事务号,并且会以这个事务号申请一个事务锁,锁级别是7级锁ExclusiveLock。事务锁用于控制记录的并发修改,比如,两个事务先后修改同一条记录,在前一个事务未结束之前,后一个事务会等待在前一个事务的事务锁上。2,记录锁当出现并发更新冲突时,冲突的事务会申请记录锁,锁级别是7级锁ExclusiveLock。记录锁主要是提高等待事务的优先级,在更新事务结束后,让持有记录锁的事务第一个被唤醒。3,扩展锁文件扩展时,会申请扩展锁,扩展锁的锁级别是7级锁ExclusiveLock。表、索引、fsm、vm等文件扩展时都会申请扩展锁。4,分区锁分区锁是专门针对分区表的,分区锁的意义与表锁差不多,锁级别从1-8都有。三,用户自定义锁也叫advisory lock,用户可以通过调用GaussDB(DWS) 提供的函数来自定义锁,自定义锁按照作用范围分为两类:1,事务级自定义锁作用范围在本事务内部,可以手动调用函数释放,也可以事务结束自动释放。相关函数:pg_advisory_xact_lock(key bigint)pg_advisory_xact_lock(key1 int, key2 int)pg_advisory_xact_lock_shared(key bigint)pg_advisory_xact_lock_shared(key1 int, key2 int)pg_try_advisory_xact_lock(key bigint)pg_try_advisory_xact_lock(key1 int, key2 int)pg_try_advisory_xact_lock_shared(key bigint)pg_try_advisory_xact_lock_shared(key1 int, key2 int)2,session级自定义锁作用范围跨越事务,需要手动调用相关函数进行合理的释放,session退出时也会强制释放。相关函数:pg_advisory_lock(key bigint)pg_advisory_lock(key1 int, key2 int)pg_advisory_lock_shared(key bigint)pg_advisory_lock_shared(key1 int, key2 int)pg_try_advisory_lock(key bigint)pg_try_advisory_lock(key1 int, key2 int)pg_try_advisory_lock_shared(key bigint)pg_try_advisory_lock_shared(key1 int, key2 int)其中:带shared后缀的相关函数会申请5级锁ShareLock,不带shared后缀的会申请7级锁ExclusiveLock。带try标识的相关函数表示尝试申请锁,如果申请不到,直接返回,不需锁等待四,如何查看锁等待通过查询pg_locks视图查看单个节点的锁持有和等待状态,pg_locks视图的结构如下图:其中:locktype列表示锁类型,包括表锁、事务锁、扩展锁、自定义锁等;relation列表示表的oid,如果是表锁,relation列会显示表的oidtransactionid表示事务号,如果是事务锁,transactionid列会显示session的事务号mode列表示锁级别,级别1-8级;pid列表示session的线程号;granted列表示是否持有锁,‘t’表示持有锁,‘f'表示等待锁;简单示例先创建一张表t1(a int, b int);并插入一条记录(1,1)。1,先后创建两个连接session1,session2,同时对这条记录进行更新,更新顺序如下: 2,对于session1,查看pg_locks,如下图所示session1持有的锁主要包括:1)持有表t1的3级锁RowExclusiveLock,表t1的oid是163842)持有session1的事务锁,事务号是2415620,锁级别7级(ExclusiveLock)3,对于session2,查看pg_locks,如下图所示 由于session1的更新未结束,session2需要等待,session2相关的锁主要包括:1)持有表t1的3级锁RowExclusiveLock,表t1的oid是163842)持有session2的事务锁,事务号是24156303)持有记录(1,1)的记录锁4)等待session1事务结束释放事务锁,granted为’f',申请session1的事务号对应的5级锁(ShareLock),与session1持有7级事务锁冲突,需要锁等待五,锁相关参数GaussDB(DWS) 中锁等待可以设置等待超时相关参数,一旦等锁的时间超过参数配置值会抛错。锁等待超时有两个参数::1) lockwait_timeout当出现表锁冲突的时候生效,当等待表锁的时间超过配置的时间,抛错返回,默认20分钟。2) update_lockwait_timeout当出现记录锁冲突的时候生效,如果等待记录锁的时间超过update_lockwait_timeout,抛错返回,默认20分钟。原文链接:https://bbs.huaweicloud.com/blogs/228062【推荐阅读】【最新活动汇总】DWS活动火热进行中,互动好礼送不停(持续更新中) HOT 【博文汇总】GaussDB(DWS)博文汇总1,欢迎大家交流探讨~(持续更新中)【维护宝典汇总】GaussDB(DWS)维护宝典汇总贴1,欢迎大家交流探讨(持续更新中)【项目实践汇总】GaussDB(DWS)项目实践汇总贴,欢迎大家交流探讨(持续更新中)【DevRun直播汇总】GaussDB(DWS)黑科技直播汇总,欢迎大家交流学习(持续更新中)【培训视频汇总】GaussDB(DWS) 培训视频汇总,欢迎大家交流学习(持续更新中)扫码关注我哦,我在这里↓↓↓
-
【摘要】 本文从条件表达式COALESCE为例,对比看各大数据库的类型规则差异。在日常使用中,很多人都会接触和使用不只一种数据库,遇到最常见的问题就是各数据库之间的行为表现不一致,包括但不限于数据类型差异、语法差异、函数差异等等。尤其在数据库迁移的时候,这样的问题尤为明显。那为什么会有这样的差异呢?既然有SQL标准,为什么各大数据库还是会有行为差异呢?在数据库的使用过程中,我也遇到了这样的问题,那便来说说自己的一点看法。标准是什么? 什么是标准? 最多人使用的做法就是标准,不要削足适履。 最终呈现给用户的,一定是具体大量使用需求的功能集合。而对于各大数据库来说,受限于自身的历史、架构和技术路线,一些功能的出现,总是结合着当时的某些业务场景的,这就导致最终呈现的形式会有差异。而这种差异是应该被理解的,不能因此而忽略各大数据库的优点。最近在使用条件表达式COALESCE的时候,发现这种差异尤为明显,类似的使用还有CASE、NVL、IF、IFNULL、NULLIF等。调用方式OracleTeradataMySQLPostgreSQLGaussDB(DWS)COALESCE(expr1,expr2...)√√√√√CASE... result_n√√√√√NVL(expr1,expr2)√√√IF(bool_value,expr1,expr2)√IFNULL(expr1,expr2)√NULLIF(expr1,expr2)√√√√√接下来就以COALESCE为例,看下各数据库之间的差异表现。1、回顾下COALESCE的定义COALESCE(expr1, expr2, ..., exprn)COALESCE返回它的第一个非NULL的参数值。如果参数都为NULL,则返回NULL。它常用于在显示数据时用缺省值替换NULL。和CASE表达式一样,COALESCE只计算用来判断结果的参数,即在第一个非空参数右边的参数不会被计算。COALESCE的语法图如下2、各数据库的差异表现COALESCE的差异表现为入参类型和返回值类型,以下分别验证Oracle、Teradata、MySQL、PostgreSQL、GaussDB(DWS)数据库的表现结果。(1)Oracle-- number + charSQL> select coalesce(123,'456') from dual;select coalesce(123,'456') from dual *第 1 行出现错误:ORA-00932: 数据类型不一致: 应为 NUMBER, 但却获得 CHAR-- char + numberSQL> select coalesce('123',456) from dual;select coalesce('123',456) from dual *第 1 行出现错误:ORA-00932: 数据类型不一致: 应为 CHAR, 但却获得 NUMBER-- numberSQL> create table tmp1 as (select coalesce(100.01,456000) as col_1 from dual);表已创建。SQL> select COLUMN_NAME,DATA_TYPE,DATA_LENGTH from user_tab_columns where TABLE_NAME='TMP1';COLUMN_NAME--------------------------------------------------------------------------------DATA_TYPE--------------------------------------------------------------------------------DATA_LENGTH-----------COL_1NUMBER 22Oracle对于COALESCE的入参要求比较严格,不支持入参混合类型,所有入参须为相同类型。对于非数值类型,返回值类型相同;对于数值类型,返回的类型为优先级较高的数值类型。(2)Teradata-- number + charBTEQ -- Enter your SQL request or BTEQ command: select coalesce(123,'456') as a,type(a); *** Query completed. One row found. 2 columns returned. *** Total elapsed time was 1 second.a Type(a)------------ -------------------------------------------------------------- 123 VARCHAR(4) CHARACTER SET UNICODE-- char + number BTEQ -- Enter your SQL request or BTEQ command: select coalesce('123',456) b,type(b); *** Query completed. One row found. 2 columns returned. *** Total elapsed time was 1 second.b Type(b)------------------ --------------------------------------------------------123 VARCHAR(6) CHARACTER SET UNICODETeradata对混合类型的支持较好,返回值的类型是所有入参的相容集合类型且精度足够,具体情况视其所在语境而定。如果入参均为非字符类型,且类型相同,则返回该类型;如果入参均为字符类型,返回值为长度最长的字符类型;如果前者参数是数值类型,先确定优先级最高的类型,隐式转换其他参数为该类型,再返回该类型;其他情况不支持。(3)MySQL-- number + char mysql> select coalesce(123,'456');+---------------------+| coalesce(123,'456') |+---------------------+| 123 |+---------------------+1 row in set (0.00 sec)mysql> create table t1 as select coalesce(123,'456');Query OK, 1 row affected (0.04 sec)Records: 1 Duplicates: 0 Warnings: 0mysql> desc t1;+---------------------+------------+------+-----+---------+-------+| Field | Type | Null | Key | Default | Extra |+---------------------+------------+------+-----+---------+-------+| coalesce(123,'456') | varchar(3) | NO | | | |+---------------------+------------+------+-----+---------+-------+1 row in set (0.00 sec)-- char + number mysql> select coalesce('123',456);+---------------------+| coalesce('123',456) |+---------------------+| 123 |+---------------------+1 row in set (0.00 sec)mysql> create table t2 as select coalesce('123',456);Query OK, 1 row affected (0.03 sec)Records: 1 Duplicates: 0 Warnings: 0mysql> desc t2;+---------------------+------------+------+-----+---------+-------+| Field | Type | Null | Key | Default | Extra |+---------------------+------------+------+-----+---------+-------+| coalesce('123',456) | varchar(3) | NO | | | |+---------------------+------------+------+-----+---------+-------+1 row in set (0.00 sec)MySQL对混合类型的入参支持度很高,返回值的类型是所有入参的相容集合类型,但具体情况视其所在语境而定。如果用在字符串语境中,则返回结果为字符串;如果用在数值语境中,则返回结果为十进制值、实值或整数值,且精度足够的类型。(4)PostgreSQL-- number + char postgres=# create table t1 as select coalesce(123,'456');SELECT 1postgres=# \d+ t1 数据表 "public.t1" 栏位 | 类型 | Collation | Nullable | Default | 存储 | 统计目标 | 描述----------+---------+-----------+----------+---------+-------+----------+------ coalesce | integer | | | | plain | |-- char + number postgres=# create table t2 as select coalesce('123',456);SELECT 1postgres=# \d+ t2 数据表 "public.t2" 栏位 | 类型 | Collation | Nullable | Default | 存储 | 统计目标 | 描述----------+---------+-----------+----------+---------+-------+----------+------ coalesce | integer | | | | plain | |PostgreSQL对混合类型的入参提供了一定的支持,返回类型的选择却与Teradata和MySQL的相容规则不同。如果所有入参都是相同的类型,并且不是字符串常量,那么解析成这种类型;否则,优先转换为首个非字符串常量参数的类型;如果从给定的输入到所选的类型不能转换,则返回错误。(5)GaussDB(DWS)GaussDB(DWS)基于PostgreSQL进行拓展,对于COALESCE表达式有两种不同的表现,可以在CREATE DATABASE时通过指定选项DBCOMPATIBILITY进行选择。-- DBCOMPATIBILITY 默认选择 'ora'postgres=# show sql_compatibility; sql_compatibility------------------- ORA(1 row)-- number + char postgres=# create table t1 as select coalesce(123,'456');INSERT 0 1postgres=# \d+ t1 Table "public.t1" Column | Type | Modifiers | Storage | Stats target | Description----------+---------+-----------+---------+--------------+------------- coalesce | integer | | plain | |Has OIDs: no Distribute By: HASH(coalesce)Location Nodes: ALL DATANODESOptions: orientation=row, compression=no-- char + number postgres=# create table t2 as select coalesce('123',456);INSERT 0 1postgres=# \d+ t2 Table "public.t2" Column | Type | Modifiers | Storage | Stats target | Description----------+---------+-----------+---------+--------------+------------- coalesce | integer | | plain | |Has OIDs: no Distribute By: HASH(coalesce)Location Nodes: ALL DATANODESOptions: orientation=row, compression=no第1种情况的表现和PostgreSQL规则一致,属于对Oracle的拓展。-- DBCOMPATIBILITY 选择 'td'postgres=# create database tddb dbcompatibility = 'td';tddb=# show sql_compatibility; sql_compatibility------------------- TD(1 row)-- number + char postgres=# create table t1 as select coalesce(123,'456');INSERT 0 1postgres=# \d+ t1 Table "public.t1" Column | Type | Modifiers | Storage | Stats target | Description----------+------+-----------+----------+--------------+------------- coalesce | text | | extended | |Has OIDs: no Distribute By: HASH(coalesce)Location Nodes: ALL DATANODESOptions: orientation=row, compression=no-- char + number postgres=# create table t2 as select coalesce('123',456);INSERT 0 1postgres=# \d+ t2 Table "public.t2" Column | Type | Modifiers | Storage | Stats target | Description----------+------+-----------+----------+--------------+------------- coalesce | text | | extended | |Has OIDs: no Distribute By: HASH(coalesce)Location Nodes: ALL DATANODESOptions: orientation=row, compression=no第2种情况的表现基于对Teradata的拓展。入参类型完全相同时,返回类型同入参类型;入参类型分类相同时,返回类型为优先级较高的类型;入参类型分类不同时,支持数值、字符、常量字符串的混合类型,返回类型的优先级为依次为数值、字符、text;如果从给定的输入到所选的类型不能转换,则返回错误。3、总结用例OracleTeradataMySQLPostgreSQLGaussdb(ora)Gaussdb(td)COALESCE(123,'456')类型不一致varcharvarcharintegerintegertextCOALESCE('123',456)类型不一致varcharvarcharintegerintegertext从各数据库对COALESCE的返回值类型表现可以看出,基础功能表现一致,差异集中在入参类型的混合支持和返回值类型的规则选择。除了本文介绍的差异外,还有很多的差异点需要我们一点点去发掘、去吸收、去总结。对于每个开发者,只有更好的了解数据库差异,才能更好的用好的数据库,避免在学习中、应用中、开发中踩坑。原文链接:https://bbs.huaweicloud.com/blogs/226037【推荐阅读】【最新活动汇总】DWS活动火热进行中,互动好礼送不停(持续更新中) HOT 【博文汇总】GaussDB(DWS)博文汇总1,欢迎大家交流探讨~(持续更新中)【维护宝典汇总】GaussDB(DWS)维护宝典汇总贴1,欢迎大家交流探讨(持续更新中)【项目实践汇总】GaussDB(DWS)项目实践汇总贴,欢迎大家交流探讨(持续更新中)【DevRun直播汇总】GaussDB(DWS)黑科技直播汇总,欢迎大家交流学习(持续更新中)【培训视频汇总】GaussDB(DWS) 培训视频汇总,欢迎大家交流学习(持续更新中)扫码关注我哦,我在这里↓↓↓
-
【摘要】 实时TopSQL,历史TopSQL。总体介绍GaussDB(DWS)资源监控的作业级别监控,分为实时级别监控(实时TopSQL)与历史级别监控(历史TopSQL)。实时TopSQL可以完成对于运行中的SQL进行资源监控,其可以通过查询gs_wlm_sesssion_statistics查询得到。历史TopSQL可以对运行结束之后的SQL进行监控其可以通过查询gs_wlm_session_history得到相应的资源消耗信息。如图1所示,在设置enable_resource_track为on,resource_track_level为query的时候,当该SQL的执行代价大于设定的resource_track_cost的时候,就可以在实时TopSQL中查到相应的SQL执行信息,当该SQL执行结束之后对于其执行时间大于resource_track_duration的SQL即可以在历史TopSQL中查询到。在设置enable_resource_record为on的时候,每过三分钟会将gs_wlm_session_history中的数据落盘存到gs_wlm_session_info中。对于存入到gs_wlm_session_info中的数据可以通过设定topsql_rentention_time对其中的数据进行老化处理。图1TopSQL功能总体关系图实时TopSQL系统提供了query级别和算子级别的资源监控实时视图用来查询实时TopSQL。资源监控实时视图记录了查询作业运行时的资源使用情况(包括内存、下盘、CPU时间和IO等)以及性能告警信息,这里相关的视图如图3.1所示。图2实时TopSQL相关的视图对于实时TopSQL而言,其中的资源数据的更新在这个SQL执行的过程中每10s会更新收集一次。历史TopSQL系统提供了query级别和算子级别的资源监控历史视图来查询历史TopSQL。资源监控历史视图记录了查询作业运行结束时的资源使用情况(包括内存、下盘、CPU时间、IO等)和运行状态信息(包括报错、终止、异常等)以及性能告警信息。但对于由于FATAL、PANIC错误导致查询异常结束时,状态信息列只显示aborted,无法记录详细的异常信息。这里需要开启参考手册开启相应的GUC参数。这里相关的视图与表如图4.1所示。图3历史TopSQL相关的视图与表这里以query当前CN查询为例说一下这个整体的流程,当作业执行完之后就会从实时static那个视图里存储到gs_wlm_session_history这个视图当中,默认三分钟之后数据就会转存到gs_wlm_session_info这个表中,存到数据库当中。在这里需要注意的是gs_wlm_session_history是一个视图,而gs_wlm_session_info是一个实际的表。另外在配置相关的GUC时,要注意有可能会配置的hash表大小过小导致数据存储不下的情况。对于TopSQL能够支持记录的规格请详见对应版本手册中的描述。原文链接:https://bbs.huaweicloud.com/blogs/215673【推荐阅读】【最新活动汇总】DWS活动火热进行中,互动好礼送不停(持续更新中) HOT 【博文汇总】GaussDB(DWS)博文汇总1,欢迎大家交流探讨~(持续更新中)【维护宝典汇总】GaussDB(DWS)维护宝典汇总贴1,欢迎大家交流探讨(持续更新中)【项目实践汇总】GaussDB(DWS)项目实践汇总贴,欢迎大家交流探讨(持续更新中)【DevRun直播汇总】GaussDB(DWS)黑科技直播汇总,欢迎大家交流学习(持续更新中)【培训视频汇总】GaussDB(DWS) 培训视频汇总,欢迎大家交流学习(持续更新中)扫码关注我哦,我在这里↓↓↓
-
为了方便您配置数据库参数,GaussDB(DWS) 提供了参数模板的功能,参数模板中包含了一些常用的数据库参数。您可以直接在GaussDB(DWS) 管理控制台上管理参数模板,将参数模板应用到集群后,可以直接在集群的“参数修改”页面中修改参数。一、参数模板概述 参数模板是一组适用于数据仓库的参数,模板中的参数都设置了默认值,这些参数包括会话超时时间、日期和时间格式等。通过调整参数值,可以使数据库更好地适配实际业务。在创建集群时,您可以为集群指定一个参数模板,模板中的参数将被应用于该GaussDB(DWS) 集群中的所有数据库,如果您未指定参数模板,系统将为集群应用默认的参数模板。当集群创建成功后,您可以在集群“参数修改”页面修改参数,也可以在参数模板管理页面,选择其他参数模板或者创建新的参数模板重新应用到对应的集群。 GaussDB(DWS) 为每个版本的数据仓库预置了一个默认参数模板,默认参数模板不支持删除和修改。如果用户想要修改参数模板中的参数值,可以创建一个自定义参数模板,自定义参数模板中的参数值允许被修改。自定义参数模板被应用到集群后,它与集群并无关联关系,之后,如果您修改了该自定义模板中的参数值,其修改并不会同步到集群,您需要重新将该参数模板应用到集群,才能使修改后的参数值应用到集群。同样的,如果您在集群详情页面修改参数,其修改也不会同步到参数模板。参数说明 参数配置如图所示: 其中,各个参数的具体含义及配置方法如下表所示: 参数名称参数描述默认值session_timeoutSession闲置超时时间,单位为秒,0表示关闭超时限制。取值范围:0 ~ 86400。600datestyle设置日期和时间值的显示格式。ISO,MDYfailed_login_attempts输入密码错误的次数达到该参数所设置的值时,帐户将会被自动锁定。配置为0时表示不限制密码输入错误的次数。取值范围:0 ~ 1000。10timezone设置显示和解释时间类型数值时使用的时区。UTClog_timezone设置服务器写日志文件时使用的时区。UTCenable_resource_record设置是否开启资源记录功能。当SQL语句实际执行时间大于resource_track_duration参数值(默认为60s,可自行设置)时,监控信息将会归档。此功能开启后会引起存储空间膨胀及轻微性能影响,不用时请关闭。说明:归档:监控信息保存在history视图,归档在info表。归档时间为三分钟,归档后history视图中的记录会被清除。history视图GS_WLM_SESSION_HISTORY,对应存入info表GS_WLM_SESSION_INFO。history视图GS_WLM_OPERATOR_HISTORY,对应存入info表GS_WLM_OPERATOR_INFO。offresource_track_cost设置对语句进行资源监控的最小执行代价。值为-1或者执行语句代价小于10时,不进行资源监控。值大于等于0时,执行语句的代价大于等于10并且超过这个参数的设定值就会进行资源监控。SQL语句的预估执行代价可通过执行SQL命令Explain进行查询。此参数在集群版本1.5.0或以上有效。100000resource_track_duration设置当前会话资源监控实时视图中记录的语句执行结束后进行归档的最小执行时间。值为0时,资源监控实时视图中记录的所有语句都会进行历史信息归档。值大于0时,资源监控实时视图中记录的语句的执行时间超过设定值就会进行历史信息归档。60password_effect_time设置帐户密码的有效时间,临近或超过有效期系统会提示用户修改密码。取值范围为0 ~999,单位为天。设置为0表示不开启有效期限制功能。此参数在集群版本1.5.0或以上有效。90update_lockwait_timeout该参数控制并发更新同一行时单个锁的最长等待时间。当申请的锁等待时间超过设定值时,系统会报错。0表示不等待,有锁时直接报错。默认值120000,单位为毫秒。此参数在集群版本1.5.0或以上有效。120000二、创建参数模板 如果默认参数模板中的参数值无法满足业务,用户可以创建自定义参数模板,并修改其中的参数值,从而更好地适配业务。 创建参数模板操作步骤如下:登录GaussDB(DWS) 管理控制台。在左侧导航栏中,单击“参数模板管理”。单击“创建参数模板”,然后设置以下参数。· “数据库引擎”:选择一个数据库引擎。· “数据库版本”:选择一个数据库版本。· “参数模板名”:填写新参数模板的名称。 参数模板名称长度为4~64个字符,必须以字母开头,不区分大小写,可以包含字母、数字、中划线或者下划线,不能包含其他的特殊字符。· “描述”:填写新参数模板的描述信息。此参数为可选参数。三、应用参数模板到集群 集群创建成功后,用户可以为集群应用一个新的参数模板,将参数模板中所有参数的值应用到对应的集群中。 应用参数模板的操作步骤如下:登录GaussDB(DWS) 管理控制台。在左侧导航栏中,单击“参数模板管理”。选择一个目标参数模板,在“操作”列中单击“应用”。在“参数模板应用”对话框,选择目标集群。单击“确定”。 如果重新应用的参数模板与集群原来的参数取值不同,系统会弹窗显示两组参数值的对比。四、删除参数模板 对于多余或者不再使用的参数模板,用户可以将其删除,但是不支持删除默认参数模板。成功删除的参数模板无法恢复,请用户谨慎操作。登录GaussDB(DWS) 管理控制台。在左侧导航栏中,单击“参数模板管理”。在待删除的参数模板右侧操作列,单击“删除”。在弹出的对话框,单击“是”。原文链接:https://bbs.huaweicloud.com/blogs/212712【推荐阅读】【最新活动汇总】DWS活动火热进行中,互动好礼送不停(持续更新中) HOT 【博文汇总】GaussDB(DWS)博文汇总1,欢迎大家交流探讨~(持续更新中)【维护宝典汇总】GaussDB(DWS)维护宝典汇总贴1,欢迎大家交流探讨(持续更新中)【项目实践汇总】GaussDB(DWS)项目实践汇总贴,欢迎大家交流探讨(持续更新中)【DevRun直播汇总】GaussDB(DWS)黑科技直播汇总,欢迎大家交流学习(持续更新中)【培训视频汇总】GaussDB(DWS) 培训视频汇总,欢迎大家交流学习(持续更新中)扫码关注我哦,我在这里↓↓↓
-
背景Hadoop的诞生是划时代的数据变革,但关系型数据库时代的存留也为Hadoop真正占领数据库领域埋下了许多的障碍。对SQL(尤其是PL/SQL)的支持一直是Hadoop大数据平台在替代旧数据时代亟待解决的问题。Hadoop对SQL数据库的支持度一直是企业用户最关心的诉求点之一,也是他们选择的Hadoop平台的重要标准。Hadoop开源技术具有高扩展性,实际生产环境已经可以支持部署几千个 物理节点,提供PB级数据分析能力,支持运行在通用廉价的x86 Linux服 务器上,数据存储在内置盘上,且无商业软件license费用;Hadoop通过技术能力(sql支持,MR内存计算,MPP)的演进以及众多 非传统关系型数据库厂商的支持,正在从最初的只处理低价值低密度数 据的批处理型任务,向中等价值数据的分析处理任务演进。融合大数据生态与MPPDB传统数据库的融合方案有以下两种:(1)远程查询方案,以关系型数据库作为集成节点,将查询发送给Hadoop,并接收Hadoop的计算结果,查询分析在Hadoop平台完成,采用这种方式的厂商有 Oracle,Teradata,SQL Server等;(2)查询引擎直接访问HDFS数据方案,分析由传统数据库引擎完成,代表产品有PIVOTAL HAWQ,IBM BigSQL 3.0等。出于性能考虑GaussDB(DWS)选择的是第二种方案。CN将任务分解下发至各个DN,以实现节点间并行,使得调度计算节点更靠近数据存储节点。特点支持多DN并发查询;支持和本地多表join;支持analyze收集统计信息;格式支持丰富,易扩展。使用用户通过建立外部服务器Server(外部服务器是存储HDFS集群信息、OBS服务器信息或其他同构集群信息的载体)-- 创建HDFS_Server。CREATE hdfs_server FOREIGN DATA WRAPPER HDFS_FDW OPTIONS ( address '10.10.0.100:25000,10.10.0.101:25000', hdfscfgpath '/opt/hadoop_client/HDFS/hadoop/etc/hadoop', type'HDFS');创建Foreign Table在GaussDB(DWS)数据库内部定义对应的HDFS/OBS数据源上结构化数据表的结构。-- 建立不包含分区列的HDFS外表,表关联的HDFS server为hdfs_server,表region对应的HDFS服务器上的文件格式为‘orc’,在HDFS文件系统上对应的文件目录为'/user/hive/warehouse/mppdb.db/region_orc11_64stripe/'。CREATE FOREIGN TABLE region( R_REGIONKEY INT4, R_NAME TEXT, R_COMMENT TEXT)SERVER hdfs_serverOPTIONS( FORMAT 'orc', encoding 'utf8', FOLDERNAME '/user/hive/warehouse/mppdb.db/region_orc11_64stripe/')DISTRIBUTE BY roundrobin;查看外表-- 查看外表。SELECT * FROM pg_foreign_table WHERE ftrelid='region'::regclass; ftrelid | ftserver | ftwriteonly | ftoptions---------+----------+-------------+------------------------------------------------------------------------------ 16510 | 16509 | f | {format=orc,foldername=/user/hive/warehouse/mppdb.db/region_orc11_64stripe/}(1 row)本章简单介绍了GaussDB(DWS)通过外表访问HDFS/OBS上的文件,下一篇中将介绍SQL On Hadoop系统分类,以及业内主流的SQL On Hadoop系统,如HIve、Impala、HAWQ等。原文链接:https://bbs.huaweicloud.com/blogs/209157【推荐阅读】【最新活动汇总】DWS活动火热进行中,互动好礼送不停(持续更新中) HOT 【博文汇总】GaussDB(DWS)博文汇总1,欢迎大家交流探讨~(持续更新中)【维护宝典汇总】GaussDB(DWS)维护宝典汇总贴1,欢迎大家交流探讨(持续更新中)【项目实践汇总】GaussDB(DWS)项目实践汇总贴,欢迎大家交流探讨(持续更新中)【DevRun直播汇总】GaussDB(DWS)黑科技直播汇总,欢迎大家交流学习(持续更新中)【培训视频汇总】GaussDB(DWS) 培训视频汇总,欢迎大家交流学习(持续更新中)扫码关注我哦,我在这里↓↓↓
上滑加载中
推荐直播
-
华为云码道Agent集成与鸿蒙实战2026/08/11 周二 19:00-21:00
王一男-华为云码道产品规划专家;李炎-华为云码道产品专家;彭江敏-华为云鸿蒙端云一体化开发专家
本次直播带你解读华为云码道7月份产品新特性、新功能。更有专家演示码道Agent Space × 钉钉机器集成实战,从0到1打通消息通道;码道鸿蒙端云一体化实战,快速搭建员工签到系统。
回顾中 -
华为云开发者AI素养直播课·第五期2026/09/04 周五 16:00-18:00
林华鼎-华为云AI开发者运营负责人;蒋春阳-华为云AI开发者案例开发专家
本期直播内容: AI工具体验营 · 第5-8课连讲。Agent-Team 多智能体协作完成毕业设计实践
回顾中 -
华为云开发者AI素养ClassRoom·第六期2026/09/08 周二 19:00-20:00
樊渊-2026华为软件挑战赛冠军
高手来了:看软挑高手解析二维排样问题—从工业难题到算法突破
回顾中
热门标签