• Navicat连接openGauss
    navicat连接openGauss配置pg_hba.confsu - ommvi /gauss/data/db1/pg_hba.conf通过cmd ipconfig指令查询客户端ip地址在配置文件中# IPv4 local connection下加入下列行,加密方式修改为md5host all all [客户端ip] md5修改密码加密方式vi /gauss/data/db1/postgresql.conf找到注释password_encryption_type = 2 ,解除注释将值改为0,表示修改加密方式为md5重启openGaussgs_om -t restart修改用户密码,使之用默认的加密方式重新加密连接到openGaussgsql -d postgres -p 26000 -r修改密码,注意新旧密码不能相同alter user [用户名] identified by ‘新密码’;打开Navicat,选择新建连接-postgresql,主机、端口填写openGauss服务器的ip和端口初始数据库选择postgres,用户名密码填刚刚更改后用md5加密的,点击新建连接
  • [技术干货] OpenGauss对数据进行完整性控制
     主要为创建触发器和建立约束创建约束创建主键约束(以在school模式下创建Manager基本表并为Muid添加主键约束为例)。​2、创建唯一性约束。将STUDENT表中的SNAME列设为唯一键约束。​COURSE表中的CNAME列设为唯一键约束。​3、创建外键约束为学生选课表SC的Sno添加来自学生表STUDENT的Sno的外键约束。​4、创建检查约束为管理员表MANAGER的Sex属性添加检查是否为男或女的约束。​实验内容二 创建触发器创建在学生表STUDENT更新学生学号Sno时触发的触发器。​测试触发器。​
  • openGauss与mysql兼容性
    版本新增MySQL兼容性特性介绍·数据类型:(1)支持XML类型(2)支持binary数据类型及运算符(3)支持tinyint[unsigned]·系统函数:时间/日期函数、JSON函数、DATABASE、ROW_COUNT、ANY_VALUE等;·DDL(1)支持schema级、表级、列级设置和修改默认字符集和排序规则,支持对表的字符集进行转换;(2)支持在表第一列前面或者在指定列后面添加列;(3)支持隐藏索引,设置索引向见性;(4)支持字段大小写敏感:建表的时候列名支持混合大小写,系统表信息中保留大小写,且sql语句中查询时可以忽略大小写。.DML:(1)支持对select into后面带OUTFILE、DUMPFILE和变量;(2)支持LOAD DATA语句导入表数据;(3) distinct支持order by带表达式;(4) select支持force关键字强制走索引;(5)视图支持插入、删除和更新,最终转换成对依赖的基表的操作!(6)支持default函数用于SQL语句;.DCL:(1)支持set transaction语法,设置会话和全局的隔离级别;(2)支持事件调度器,支持创建、修改.别除event操作;(3)支持show status、show warning和show errors等;(4)支持'user @'host'形式指定用户;·PL/SQL:(1)支持WHILE循环带标签;(2)支持CASE WHEN condition和IF_THEN控制语法;(3)支持cursor相关语法;(4)存储过程支持REPEAT和RETURN;(5)支持create function前面不加as begin,末尾不加end language plpgsql;(6)支持declare handler、continue handler、exit handler;其他语法兼容:(1)支持用户自定义变量保存select语句的结果,前提是要将enable_set_variable_b_format设置为on。set enable_set_variable_b_format to on; select @aa := ’test’; select @aa;  // 返回@aa 值是test(2支持utf8_general_ci、 utf8 bin.utf8_unicode_ci、 binary等字符序;(3支持utf8mb4字符集;(4)支持操作符行为和MySQL一致;(5)支持双引号表示字符串。
  • [技术干货] opengauss事务管理
    事务:用户定义的数据库操作系列,要么全做要么全不做,是不可分割的工作单位。事务控制主要包括:启动事务、设置隔离级别、设置访问模式、提交事务、回滚事务。事务执行中,如果发生某种故障使得事务不能执行,会执行rollback将事务中所有已完成的操作全部撤销,修改的数据回到事务开始前。sql语句// 启动事务,二者等效 START TRANSACTION BEGIN隔离级别:read committed(读已提交):事务执行期间,能读到由其他并发事务提交的修改read uncommitted(脏读):事务执行期间,能读到其他并发事务未提交的修改repeatable read:事务执行期间,不能读到其他并发事务的修改注意:openGauss不支持脏读!// 设置隔离级别 SET TRANSACTION ISOLATION LEVEL READ COMMITTED SET TRANSACTION ISOLATION LEVEL REPEATABLE READ访问模式:设置为只读时,事务不允许修改数据。// 设置事务访问模式 SET TRANSACTION READ WRITE SET TRANSACTION READ ONLY // 提交事务,二者等效 COMMIT END // 回滚事务 ROLLBACK
  • 【学习笔记】openGauss权限管理(下)
     --三权分立在实际业务管理中,为了避免系统管理员拥有过度集中的权利带来高风险,可以设置三权分立。将系统管理员的部分权限分立给安全管理员和审计管理员,形成系统管理员、安全管理员和审计管理员三权分立。三权分立后,系统管理员只会对自己作为所有者的对象有权限。系统管理员将不再拥有创建角色和用户的权限,并不再拥有数据库审计日志的权限。gs_guc set命令设置三权分立gs_om -t stop && gs_om -t start命令重启数据库使参数生效​验证:通过create user创建用户并授予系统管理员权限sysadmin​连接到数据库,使用系统管理员用户尝试创建用户,发现失败。通过select命令使用系统管理员用户查看审计日志,失败。​通过create user命令with createrole创建安全管理员用户leo​使用安全管理员用户创建新用户成功。​通过create user命令with auditadmin创建审计管理员用户william​审计管理员用户可以用select查看审计日志gs_guc set取消三权分立,并重启生效​--私有用户在非三权分立情况下,为了提高数据安全性,有时希望系统管理员能够控制操作(DROP、ALTER,TRUNCATE)用户的数据,但不能进行访问操作(INSERT、DELETE、SELECT、UPDATE、COPY.GRANT、REVOKE、ALTER OWNER)用户的数据。这种情况下就可以创建具有INDEPENDENT属性的私有用户。create user命令创建具有数据库创建权限的用户rose​通过create database创建数据库rose_database,并连接​创建schema rose和rose_table​向表格插入数据,并查看​切换至管理员用户omm 发现无法查看私有用户创建的rose_table但是管理员可以进行drop/alter/truncate table,例如删除数据表​
  • 【学习笔记】openGauss权限管理(上)
     --角色权限管理用户:用来连接数据库、访问数据库对象和执行SQL语句的一个账号。用户,至少包含用户名和密码。权限:指允许用户在给定对象上执行的操作。包含给的对象和相应的操作两个部分。初始用户:安装过程中自动生成的帐号称为初始用户。初始用户拥有系统的最高权限,默认的初始用户是omm.su - omm // 切换到ommgsql -d postgres -p 26000 -r  // 连接数据库创建数据库并查看​连接数据库,创建数据表,增加数据,并查看表格数据​数据库对象创建后,创建该对象的用户就是其owner,拥有对这一对象的所有权限。接下来,用普通用户连接数据库创建用户bill,并查看用户​修改其名称为spike​删除用户spike​未被授予权限的用户无法进行响应的数据库操作。--授权场景1. 系统权限授权2. 数据库对象授权3. 角色或用户的权限授予其他角色或用户--系统权限授权系统权限又称为用户属性,包括系统管理员、创建数据库、安全管理员、审计管理员和登录。系统权限一般通过创建和修改用户与角色来指定。系统管理员权限可以通过权限的授予或撤销命令进行关联。系统权限无法通过角色和用户权限被继承。系统管理员是指具有系统管理员属性的帐户,默认安装情况下具有与对象所有者相同的权限。要创建新的系统管理员,需要以初始用户或者系统管理员用户身份连接数据库。创建用户,with sysadmin授予系统管理员权限(需要在初始用户或其他系统管理员用户下)​通过alter user命令 with nosysadmin,撤销系统管理员权限​通过grant命令授予系统管理员权限​通过revoke命令再次撤销系统管理员权限​--数据库对象授权将数据库对象授权给用户。数据库对象权限:数据库对象(表和视图、指定字段、数据库、函数、模式、表空间等)的相关权限(创建、删除、修改等)。通过create user命令创建新用户simon​通过grant命令授予price_list对象的权限,并用select查询验证​通过revoke命令撤回其权限,之后无法再进行查询​--角色或用户的权限授予其他角色或用户角色是一组权限的集合,不能登录。把角色授予用户后,用户有了角色的所有权限。通过create role命令创建角色​通过grant命令进行角色的权限授予​通过grant命令将角色权限授予具体用户,并select验证​其中的member of列表示john已经属于maintenance_engineer角色通过alter role命令修改角色名称​删除角色时,需要先revoke删除角色在对象上的权限,才能用drop role删除角色+​转自:https://www.hikunpeng.com/forum/thread-0283135314863753019-1-1.html
  • [技术干货] opengauss数据库练习
    设置Description# 为表设置注释 COMMENT ON TABLE finances_product IS '理财产品表'; # 为字段添加description comment on column fund.f_name is '基金名称';数据库安全管理# 创建数据库用户fund_app CREATE USER fund_app IDENTIFIED BY 'Gauss#3demo'; # 只赋予fund_app必需的4张表的查询权限。 GRANT select ON table bank_card to fund_app; GRANT select ON table client to fund_app; GRANT select ON table property to fund_app; GRANT select ON table fund to fund_app; # 以fund_app用户使用gsql登录openGauss。 gsql -d finance -U fund_app -W Gauss#3demo -p 26000 -r # 以bank_app用户使用gsql登录openGauss。 gsql -d finance -U bank_app -W Gauss#3demo -p 26000 -r # 使用行级访问控制,限制fund_app只能访问property表中基金相关的记录,即满足pro_type=3的记录 ALTER TABLE property ENABLE ROW LEVEL SECURITY; CREATE ROW LEVEL SECURITY POLICY property_rls ON property USING(current_user !='fund_app' or current_user ='fund_app' and pro_type =3);sql 高级语句# 执行以下SQL,通过右连接、聚合函数等SQL特性实现复杂查询。 select c_id_card, c_name,sum(pro_income) total_income from client c, bank_card b, property p, (select p_name name, p_id pro_pif_id, 1 pro_type from finances_product union all select i_name name, i_id pro_pif_id, 2 pro_type from insurance union all select f_name name, f_id pro_pif_id, 3 pro_type from fund) d where c.c_id = p.pro_c_id and c.c_id = b.b_c_id(+) and p.pro_pif_id=d.pro_pif_id and p.pro_type=d.pro_type group by c_id_card, c_name order by 2 desc; # 可通过EXPLAIN ANALYZE显示该SQL的执行计划。 explain analyze select c_id_card, c_name,sum(pro_income) total_income from client c, bank_card b, property p, (select p_name name, p_id pro_pif_id, 1 pro_type from finances_product union all select i_name name, i_id pro_pif_id, 2 pro_type from insurance union all select f_name name, f_id pro_pif_id, 3 pro_type from fund) d where c.c_id = p.pro_c_id and c.c_id = b.b_c_id(+) and p.pro_pif_id=d.pro_pif_id and p.pro_type=d.pro_type group by c_id_card, c_name order by 2 desc;健康检查# 获取gs_check所在的路径 dirname `which gs_check` /opt/install/om/script/ # 查找参数 find /opt/install/om/script/gspylib/inspection/items/ |grep '.py$' | awk -F/ '{print $(NF-1), substr($NF,1,length($NF)-3)}' # 创建文件把所有输出结果保存到文件中 find /opt/install/om/script/gspylib/inspection/items/ |grep '.py$' | awk -F/ '{print $(NF-1), substr($NF,1,length($NF)-3)}' > 1.txt # 执行命令实现对所有数据库检测项目的检测 for i in `cat 1.txt`; do gs_check -L -i $i; done # -L 中文显示通过信息 # 对CheckUnAnalyzeTable所返回的finance数据库的表进行analyze操作,以omm用户登录到finance数据库上。 gsql -p 15400 -d finance -r finance=# analyze insurance; ANALYZE finance=# analyze bank_card; ANALYZE finance=# analyze client; ANALYZE finance=# analyze finances_product; ANALYZE finance=# analyze property; ANALYZE finance=# analyze fund; ANALYZE finance=# analyze dbe_pldeveloper.gs_source; ANALYZE # 重新检查 gs_check -L -i CheckUnAnalyzeTable性能检查# 显示集群简单信息 su - omm gs_checkperf # 以omm用户运行gs_checkperf命令,显示当前集群的详细信息 gs_checkperf -i PMK --detail日志收集使用 gs_collector收集OS信息、日志信息以及配置文件等信息,并查看每个日志的内容# 执行gs_collector命令,请修改时间戳为当前合适的值 gs_collector --begin-time='20231101 07:00' --end-time='20231107 16:10' ...... All results are stored in /var/log/omm/omm/collector_20231020_072319.tar.gz. # 解压缩收集到的压缩文件 tar zxvf /var/log/omm/omm/collector_20231020_072319.tar.gz cd collector_20231020_072319/ # 进一步解压缩以当前节点名字命名的压缩文件 tar zxvf ecs-840f.tar.gz # 查看收集到的操作系统的状态信息。 vi ecs-840f/systemfiles/OS_information_*.txt # 查看收集到的数据库的状态信息 vi ecs-840f/systemfiles/database_system_info_*.txt # 查看收集到的pg_stat_activity、pg_locks、pg_thread_wait_status三个视图的内容 vi ecs-840f/catalogfiles/*_pg_* # 查看收集到的配置文件postgresql.conf、pg_ident.conf和pg_hba.conf的内容 vi ecs-840f/configfiles/config_*/dn_6001/*.conf参数设置有一些数据库参数是需要数据库管理员特别关注和调整的,一个例子是结合操作系统的内存大小,设置数据库shared buffer的大小。# 查看操作系统内存 free -h # 使用gsql客户端以管理员用户身份连接postgres数据库 gsql -d postgres -p 15400 -r # 查看数据库 shared buffer 的大小 show shared_buffers; # 调整 shared buffer 参数 alter system set shared_buffers='10GB'; # 停止数据库 gs_om -t stop # 启动数据库 gs_om -t start ; # 验证参数设置是否成功 gsql -d postgres -p 26000 -r -c 'show shared_buffers'后台维护在对数据频繁删除更新后,使用VACUUM、REINDEX、ANALYZE等命令维护表和索引。delete from many_clients where gid>1; # # 登录到数据库 gsql -d finance -p 26000 -r # 运行以下查询,生成测试表 many_clients。注意:创建该表前确认enable_default_ustore_table=off。否则运行下列命令修改参数后,并重启数据库。gs_guc set -N all -I all -c "enable_default_ustore_table=off" create table many_clients as select c.*, generate_series gid from client c, generate_series(1, 10000) ; create index mc_gid on many_clients(gid); # 对many_clients执行analyze analyze verbose many_clients; # 查看many_clients表的大小。 \dt+ many_clients; # 查看my_gid 索引的大小 \di+ my_gid # 使用delete 语句删除大约 99%的数据 delete from many_clients where gid>1; # 对many_clients执行analyze。 analyze verbose many_clients; # 查看many_clients 表的大小 \dt+ many_clients; # 查看my_gid 索引的大小 \di+ my_gid # 使用VACUUM对表many_clients进行磁盘空间回收 vacuum full many_clients; # 对many_clients执行analyze。 analyze verbose many_clients; # 查看many_clients表的大小。 \dt+ many_clients; # 使用REINDEX重建mc_gid索引 REINDEX INDEX mc_gid; # 查看my_gid 索引的大小 \di+ my_gidWDR 报告基于过去两个快照,生成WDR报告,并进行解读;步骤 1 以omm用户登录数据库postgres。 gsql -d postgres -p 26000 -r 步骤 2 显示enable_wdr_snapshot的值。 openGauss=# show enable_wdr_snapshot; enable_wdr_snapshot --------------------- off (1 row) 步骤 3 若enable_wdr_snapshot为off,使用以下命令设置为on。 openGauss=# alter system set enable_wdr_snapshot=on; ALTER SYSTEM SET 步骤 4 查询当前存在的快照。 openGauss=# select * from snapshot.snapshot; snapshot_id | start_ts | end_ts -------------+------------------------------+------------------------------- 1 | 2023-10-21 07:59:36.85467+08 | 2023-10-21 07:59:38.064506+08 (1 row) 步骤 5 若当前只有一个快照,重建出一个新快照。 openGauss=# select create_wdr_snapshot(); create_wdr_snapshot ----------------------------------------- WDR snapshot request has been submitted (1 row) 步骤 6 查询当前存在的快照,确保新快照已经生成。 openGauss=# select * from snapshot.snapshot; snapshot_id | start_ts | end_ts -------------+-------------------------------+------------------------------- 1 | 2023-10-21 07:59:36.85467+08 | 2023-10-21 07:59:38.064506+08 2 | 2023-10-21 08:13:33.540987+08 | 2023-10-21 08:13:34.717914+08 (2 rows) 步骤 7 利用最近的两个快照,生成一份WDR报告。 openGauss=# \a \t \o wdr.html Output format is unaligned. Showing only tuples. openGauss=# select generate_wdr_report(1, 2, 'all', 'node', pgxc_node_str()::cstring); openGauss=# \o 步骤 8 退出gsql,把wdr.html下载到本地,使用浏览器打开,查看Top 5等待事件和Top SQL。密态查询在客户表中增加一列,并设置为加密列。通过在客户端查询数据,并赋值给该加密列,验证该列的数据在服务器上已经自动加密。 # 步骤 1 以omm用户,创建密态数据库所需的KMS目录。 [omm@ecs-840f lab]$ mkdir -p $GAUSSHOME/etc/localkms/ # 步骤 2 以omm用户登录到数据库finance上,并打开-C密态开关。 gsql -p 26000 finance -r -C # 步骤 3 创建CLIENT MASTER KEY。 finance=# CREATE CLIENT MASTER KEY finCMK WITH (KEY_STORE = localkms, KEY_PATH = "finance", ALGORITHM = RSA_2048); CREATE CLIENT MASTER KEY # 步骤 4 创建COLUMN ENCRYPTION KEY。 finance=# CREATE COLUMN ENCRYPTION KEY finCEK WITH VALUES (CLIENT_MASTER_KEY = finCMK, ALGORITHM = AEAD_AES_256_CBC_HMAC_SHA256); CREATE COLUMN ENCRYPTION KEY # 步骤 5 为client表增加加密列c_name_e。 finance=# ALTER TABLE client ADD COLUMN c_name_e VARCHAR(100) ENCRYPTED WITH (COLUMN_ENCRYPTION_KEY = finCEK, ENCRYPTION_TYPE = DETERMINISTIC); ALTER TABLE # 步骤 6 查询c_id=1的用户姓名。 finance=> select c_name from client where c_id=1; # 步骤 7 执行update语句,把查询到的值更新到c_name_e列。 finance=# update client set c_name_e='左晓婷' where c_id=1; # 步骤 8 执行查询语句。 finance=# select c_name_e from client where c_id=1; # 步骤 9 退出gsql,并重新登录,不打开-C密态开关。 gsql -p 26000 finance -r # 步骤 10 验证c_name_e的值是否加密。 finance=# select c_name_e from client where c_id=1;账本数据库把资产表改造为基于账本数据库的防篡改表,故意增大某个客户某笔交易的交易量,通过查询系统视图,显示该行记录的所有修改历史# 步骤 1 以omm用户登录到finance数据库。 gsql -d finance -p 26000 -r # 步骤 2 查询账本数据库schema。 finance=# CREATE SCHEMA ledgernsp WITH BLOCKCHAIN; CREATE SCHEMA # 步骤 3 在该schema下面,创建新的资产表。 finance=# create table ledgernsp.property ( pro_c_id int PRIMARY KEY, pro_id INT NOT NULL, pro_status CHAR(20), pro_quantity INT, pro_income INT, pro_purchase_time DATE ); NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "property_pkey" for table "property" CREATE TABLE # 步骤 4 从原来的资产表中查询并插入到新的资产表中。 finance=# insert into ledgernsp.property select * from property; INSERT 0 4 # 步骤 5 查询property表的数据。 finance=# select *,hash from ledgernsp.property; pro_id | pro_c_id | pro_pif_id | pro_type | pro_status | pro_quantity | pro_income | pro_purchase_time | hash --------+----------+------------+----------+--------------------+--------------+------------+---------------------+------------------ 1 | 5 | 1 | 1 | 可用 | 4 | 8000 | 2018-07-01 00:00:00 | f3de57e69253919e 2 | 10 | 2 | 2 | 可用 | 4 | 8000 | 2018-07-01 00:00:00 | c81d20819d5917d6 3 | 15 | 3 | 3 | 可用 | 4 | 8000 | 2018-07-01 00:00:00 | a57b0e921843d811 4 | 20 | 4 | 1 | 冻结 | 4 | 8000 | 2018-07-01 00:00:00 | 225f6c904e149e9d (4 rows) # 步骤 6 把pro_c_id为10的交易的pro_quantity的值从4改为5。 finance=# update ledgernsp.property set pro_quantity = 5 where pro_c_id=10; UPDATE 1 # 步骤 7 查询property表的内容。 finance=# select *,hash from ledgernsp.property; pro_id | pro_c_id | pro_pif_id | pro_type | pro_status | pro_quantity | pro_income | pro_purchase_time | hash --------+----------+------------+----------+--------------------+--------------+------------+---------------------+------------------ 1 | 5 | 1 | 1 | 可用 | 4 | 8000 | 2018-07-01 00:00:00 | f3de57e69253919e 3 | 15 | 3 | 3 | 可用 | 4 | 8000 | 2018-07-01 00:00:00 | a57b0e921843d811 4 | 20 | 4 | 1 | 冻结 | 4 | 8000 | 2018-07-01 00:00:00 | 225f6c904e149e9d 2 | 10 | 2 | 2 | 可用 | 5 | 8000 | 2018-07-01 00:00:00 | 5aa59018a53ddc7c (4 rows) # 步骤 8 查询property历史表的内容。 finance=# select * from blockchain.ledgernsp_property_hist; rec_num | hash_ins | hash_del | pre_hash ---------+------------------+------------------+---------------------------------- 0 | f3de57e69253919e | | b2f0373e538907da708489dd3eab1caf 1 | c81d20819d5917d6 | | 80c9a338e81b73334b123fb76b76ec33 2 | a57b0e921843d811 | | 9d1b724a131fbbf87f3b0fb343f138c1 3 | 225f6c904e149e9d | | 5f391dbe6dd01584b5e9a37a5dcbb0f9 4 | 5aa59018a53ddc7c | c81d20819d5917d6 | 5c4c248e73b2cb97d6d4113b9d2b0356 (5 rows) # 步骤 9 查询gs_global_chain的内容,显示刚才执行的两个DML操作。 finance=# SELECT * FROM gs_global_chain; blocknum | dbname | username | starttime | relid | relnsp | relname | relhash | globalhash | txcommand ----------+---------+----------+-------------------------------+-------+-----------+----------+------------------+----------------------------------+---- ---------------------------------------------------------- 1 | finance | omm | 2023-10-21 10:12:27.916749+08 | 17540 | ledgernsp | property | 83d5f38a96052022 | fb01ebb45d887101353477022b02750e | insert into ledgernsp.property select * from property; 2 | finance | omm | 2023-10-21 10:16:15.733258+08 | 17540 | ledgernsp | property | 92886f9707e4c4a6 | 63be71a0b61971364c12aa5d958b9f7a | update ledgernsp.property set pro_quantity = 5 where pro_c_id=10; (2 rows) # 步骤 10 把pro_c_id为10的交易的pro_quantity的值从5改为8。 gsql -d finance -p 26000 -r # 步骤 11 查询property表,获取pro_c_id为10的交易对应的hash值。 finance=# select *,hash from ledgernsp.property where pro_c_id=10; pro_id | pro_c_id | pro_pif_id | pro_type | pro_status | pro_quantity | pro_income | pro_purchase_time | hash --------+----------+------------+----------+--------------------+--------------+------------+---------------------+------------------ 2 | 10 | 2 | 2 | 可用 | 8 | 8000 | 2018-07-01 00:00:00 | 7b27d899cca5b211 (1 row) # 步骤 12 执行以下SQL,联合blockchain.ledgernsp_property_hist和视图gs_global_chain,显示该交易历史的所有修改记录。 finance=> WITH RECURSIVE res AS ( SELECT xmin, rec_num, hash_ins::varchar,hash_del::varchar FROM blockchain.ledgernsp_property_hist WHERE hash_ins::varchar = '7b27d899cca5b211' UNION SELECT m.xmin, m.rec_num, m.hash_ins::varchar || ' > ' || r.hash_ins::varchar, m.hash_del::varchar FROM res r INNER JOIN blockchain.ledgernsp_property_hist m ON m.hash_ins::varchar = r.hash_del::varchar ) select res.*,gc.starttime,gc.txcommand from res inner join gs_global_chain gc on res.xmin = gc.xmin; xmin | rec_num | hash_ins | hash_del | starttime | txcommand -------+---------+--------------------------------------------------------+------------------+-------------------------------+-------------------------------------------- - 72081 | 5 | 7b27d899cca5b211 | 5aa59018a53ddc7c | 2023-10-21 11:52:00.423596+08 | update ledgernsp.property set pro_quantity= 72057 | 4 | 5aa59018a53ddc7c > 7b27d899cca5b211 | c81d20819d5917d6 | 2023-10-21 10:16:15.733258+08 | update ledgernsp.property set pro_quantity 72056 | 1 | c81d20819d5917d6 > 5aa59018a53ddc7c > 7b27d899cca5b211 | | 2023-10-21 10:12:27.916749+08 | insert into ledgernsp.property select * fro (3 rows) 结束。union 子句步骤 1 合并表t_demo和表t_demo_copy的数据,并去掉重复的数据。 openGauss=# SELECT * FROM t_demo UNION SELECT * FROM t_demo_copy; id | name | age | num ----+--------+-----+----- 2 | 李四 | 22 | 98 5 | 孙悟空 | 22 | 100 6 | 李四 | 24 | 99 3 | 王五 | 20 | 54 4 | 赵甜 | 22 | 80 2 | 猪八戒 | 22 | 98 1 | 张三 | 21 | 69 (7 rows) 步骤 2 合并表t_demo和表t_demo_copy的数据,不去掉重复的数据。 openGauss=# SELECT * FROM t_demo UNION ALL SELECT * FROM t_demo_copy; id | name | age | num ----+--------+-----+----- 1 | 张三 | 21 | 69 2 | 李四 | 22 | 98 3 | 王五 | 20 | 54 4 | 赵甜 | 22 | 80 1 | 张三 | 21 | 69 2 | 猪八戒 | 22 | 98 3 | 王五 | 20 | 54 4 | 赵甜 | 22 | 80 5 | 孙悟空 | 22 | 100 6 | 李四 | 24 | 99 (10 rows)子查询派生表FROM 子句中的子查询被称为派生表(Derived table)。其中子查询相当于创建了一个临时表 table_alias。# 查询部门名和部门的平均月薪。 子查询返回了部门编号和部门平均月薪,然后再和 departments 表进行连接查询 openGauss=# SELECT d.department_name, ds.sum_salary FROM departments d JOIN (SELECT department_id, ROUND(AVG(salary), 2) AS sum_salary FROM employees group by department_id ) ds ON (d.department_id = ds.department_id); department_name | sum_salary -------------------------+------------ Purchasing | 6900.00 Shipping | 3750.00 IT | 4800.00 Sales | 14000.00 Executive | 17000.00 Finance | 7300.00in 操作符WHERE子查询返回多个记录,可以使用 IN 操作符进行条件过滤。Where子查询返回的记录中等于IN列表中的某一个值。# 查询有员工薪资大于5000的部门编号和部门名称。 openGauss=# SELECT d.department_id, d.department_name FROM departments d WHERE d.department_id in (SELECT department_id FROM employees WHERE salary > 5000); department_id | department_name ---------------+----------------- 30 | Purchasing 80 | Sales 90 | Executive 100 | FinanceALL操作符WHERE 子查询返回多个记录,与ALL操作符列表的所有值进行比较过滤。# 查询薪资比部门编号为30的所有员工都高的员工姓名,薪资。 openGauss=# SELECT first_name, last_name, salary FROM employees WHERE salary > ALL(SELECT salary FROM employees WHERE department_id =30); first_name | last_name | salary ---------------+----------------+---------- Neena | Kochhar | 17000.00 John | Russell | 14000.00ANY 操作符WHERE子查询返回多个记录,与ANY操作符列表的任意值进行比较过滤。# 查询薪资比部门编号为30的任意员工都高的员工姓名,薪资。 SELECT first_name, last_name, salary FROM employees WHERE salary > ANY(SELECT salary FROM employees WHERE department_id =30); first_name | last_name | salary -----------------+-----------+---------- Neena | Kochhar | 17000.00 Ismael | Sciarra | 7700.00 Luis | Popp | 6900.00 Den | Raphaely | 11000.00 David | Austin | 4800.00 Valli | Pataballa | 4800.00 Alexis | Bull | 4100.00 Julia | Dellinger | 3400.00 John | Russell | 14000.00EXISTS 操作符EXISTS 操作符用于检查子查询结果的存在性。如果子查询返回任何结果,EXISTS 返回 True,否则返回False。# 查询员工薪资有超过5000的部门编号和部门名。 openGauss=# SELECT d.department_id, d.department_name FROM departments d WHERE exists (SELECT * FROM employees WHERE department_id = d.department_id and salary > 5000); department_id | department_name ---------------+----------------- 30 | Purchasing 80 | Sales 90 | Executive 100 | Finance关联子查询关联子查询会引用外部查询中的列,因而与外部查询产生关联# 查询员工薪大于所在部门平均月薪的员工姓名和薪资。 子查询中引用了外查询中的o.department_id。 openGauss=# SELECT first_name, last_name, salary FROM employees o WHERE o.salary >(SELECT avg(salary) FROM employees i WHERE i.department_id = o.department_id); first_name | last_name | salary ------------+-----------+---------- Ismael | Sciarra | 7700.00 Den | Raphaely | 11000.00 Alexis | Bull | 4100.00 # 步骤 2 查询部门编号,部门名和对应部门每个月的总薪资。 子查询中引用了外查询departments表的department_id列。 openGauss=# SELECT department_id, d.department_name, (SELECT SUM(salary) FROM employees e WHERE e.department_id = d.department_id) AS sum_salary FROM departments d; department_id | department_name | sum_salary -----------------------+----------------------------+------------ 10 | Administration | 20 | Marketing | 30 | Purchasing | 13800.00 40 | Human Resources | 50 | Shipping | 7500.00 60 | IT | 9600.00 70 | Public Relations | 80 | Sales | 14000.00 90 | Executive | 17000.00 100 | Finance | 14600.00 (10 rows)INSER_T/UPDATE语句中的子查询使用步骤 1 创建新表employees_new。 openGauss=# CREATE TABLE employees_new ( employee_id integer NOT NULL, first_name character varying(20), last_name character varying(25) NOT NULL, hire_date timestamp(0) without time zone NOT NULL, salary numeric(8,2), department_id integer, CONSTRAINT emp_salary_min CHECK ((salary > (0)::numeric)) ); CREATE TABLE 步骤 2 将employees表中薪资大于5000的员工所有信息录入employees_new表中。 openGauss=# insert into employees_new select * from employees e where e.employee_id in(select e.employee_id from employees where e.salary > 5000); INSERT 0 5 openGauss=# select * from employees_new; employee_id | first_name | last_name | hire_date | salary | department_id -------------------+---------------+---------------------+---------------------------------+--------------+--------------- 101 | Neena | Kochhar | 2005-09-21 00:00:00 | 17000.00 | 90 111 | Ismael | Sciarra | 2005-09-30 00:00:00 | 7700.00 | 100 113 | Luis | Popp | 2007-12-07 00:00:00 | 6900.00 | 100 114 | Den | Raphaely | 2002-12-07 00:00:00 | 11000.00 | 30 145 | John | Russell | 2004-10-01 00:00:00 | 14000.00 | 80 步骤 3 修改employees_new表中薪资大于10000的员工修改薪资降为原薪资的50%。 openGauss=# update employees_new set salary = salary * 0.5 where employee_id in(select employee_id from employees_new where salary > 10000); openGauss=# select * from employees_new; employee_id | first_name | last_name | hire_date | salary | department_id --------------------+-------------------+-----------+---------------------+---------+--------------- 111 | Ismael | Sciarra | 2005-09-30 00:00:00 | 7700.00 | 100 113 | Luis | Popp | 2007-12-07 00:00:00 | 6900.00 | 100 101 | Neena | Kochhar | 2005-09-21 00:00:00 | 8500.00 | 90 114 | Den | Raphaely | 2002-12-07 00:00:00 | 5500.00 | 30 145 | John | Russell | 2004-10-01 00:00:00 | 7000.00 | 80 常用函数数值计算函数步骤 1 ABS(X)函数用户计算X的绝对值。 openGauss=# select abs(-15.9); abs ------ 15.9 (1 row) 步骤 2 ceil(exp) 返回大于或者等于指定表达式n的最小整数。 openGauss=# select ceil(15.3); ceil ------ 16 (1 row) 步骤 3 floor (exp) 小于或等于表达式值的最近的整数。 openGauss=# select floor(15.3); floor ------- 15 (1 row) 步骤 4 power(base, expn) 返回数字乘幂的计算结果。base表示底数,expn表示指数。返回值是number。 openGauss=# select power(5,3); power ------- 125 (1 row) 步骤 5 div(y, x)函数计算 y 除以 x 的整数商,mod(y, x)函数计算 y 除以 x 的余数。 openGauss=# SELECT div(11,3), mod(11,3); div | mod -----+----- 3 | 2 (1 row) 步骤 6 random()函数提供了用于返回一个随机数。 openGauss=# SELECT random(); random ------------------ .781858928501606 (1 row) openGauss=# SELECT random(); random ------------------ .545018189121038 (1 row)字符处理函数步骤 1 concat(str[,…]),concat_ws(separator,str1,str2,…):拼接一个或多个字符串。第一个函数无分隔符,第二个函数可以指定分隔符连接。 openGauss=# select concat('123','xyz','456'); concat ----------- 123xyz456 (1 row) openGauss=# select concat_ws('-','123','xyz','456'); concat_ws ------------- 123-xyz-456 (1 row) 步骤 2 replace(str,src,dst):字符串插入和字符串替换函数。 openGauss=# select replace('12345623','23','xyz'); replace ------------ 1xyz456xyz (1 row) 步骤 3 instr(str1,str2[,pos[,n]])):字符串查找函数。返回要查找的字符串在源字符串中的位置。返回在string1中从int1位置开始匹配到第int2次string2的位置,第一个int表示开始匹配起始位置,第二个int表示匹配的次数。 openGauss=# SELECT INSTR('123456abcd123456abcd', '45'), INSTR('123456abcd123456abcd', 'bcd', 1, 2 ); instr | instr -------+------- 4 | 18 (1 row) 步骤 4 lower(string)函数将字符串转换为小写形式,upper(string)函数将字符串转换为大写形式。 openGauss=# SELECT lower('JAMES'), upper('James'); lower | upper -------+------- james | JAMES (1 row) 步骤 5 substr(str, start[, len])字符串截取函数,表示字符串str从start位置截取长度为len的字符串 openGauss=# select substr('abcdefg',3,4); substr -------- cdef (1 row)时间日期函数步骤 1 age(timestamp, timestamp)函数用于计算两个时间点之间的间隔。 openGauss=# SELECT age(timestamp '2023-09-30', timestamp '2023-09-05'); age --------- 25 days (1 row) 步骤 2 current_timestamp获取当前系统时间及时区,current_date获取当前日期。 openGauss=# select current_timestamp,current_date; pg_systimestamp | date -------------------------------------------------+----------------- 2023-09-14 08:41:24.920154+08 | 2023-09-14 (1 row)类型转换函数步骤 1 cast(expr as datatype) 将值转换为指定的数据类型,换运算符(::)也可实现相同功能。 openGauss=# SELECT CAST ('201' AS INTEGER), '2023-09-15'::DATE; int4 | timestamp ------+--------------------- 201 | 2023-09-15 00:00:00 (1 row) 步骤 2 to_date(string, format)函数用于将字符串 string 按照 format 格式转换为日期类型。 openGauss=# select to_date('2023/09/15','YYYY/MM/DD'); to_date --------------------- 2023-09-15 00:00:00 步骤 3 to_char (datetime/interval [, fmt]),转换为字符串。 openGauss=# SELECT to_char(current_timestamp, 'HH24:MI:SS'); to_char ---------- 09:02:36系统信息函数步骤 1 查询数据库实例启动时间、当前数据库名称(在标准SQL中称“catalog”)和主机名称。 openGauss=# select pg_postmaster_start_time(),current_catalog,current_database(),get_hostname(); pg_postmaster_start_time | current_database | current_database | get_hostname ----------------------------------------------+--------------------------+-------------------------+-------------- 2023-09-27 10:25:27.886419+08 | postgres | postgres | Run861 (1 row) 步骤 2 查询当前schema和搜索路径中的schema。 openGauss=# select current_schema; current_schema ------------------------ public (1 row) 步骤 3 查询当前环境下的用户和用户id。 openGauss=# select user,current_user,current_role,session_user,pg_current_userid(); current_user | current_user | current_user | session_user | pg_current_userid -------------------------+------------------------+------------------------+---------------------+------------------- omm | omm | omm | omm | 10存储过程与触发器存储过程(Stored Procedure),是存储在数据库中一组能够完成特定功能的SQL语句集,以便外部程序调用的数据库对象。可以视为数据库的一种函数或子程序。一次编写,反复调用,从而减少SQL语句的重复编写数量,提高工作效率。一次交互,发送更多SQL,减少了客户端服务端交互次数。对于多次运行的复杂SQL,存储过程支持缓存SQL计划,减少了生成计划的时间。简单的存储过程步骤 1 创建表t1。 openGauss=# CREATE TABLE t1( ID INT, NAME VARCHAR2(20) ); 步骤 2 创建存储过程(以存储过程 p1为例)。 openGauss=# CREATE OR REPLACE PROCEDURE p1 IS BEGIN INSERT INTO t1 VALUES(1,'李明'); COMMIT; END; / 步骤 3 调用存储过程p1。 openGauss=# call p1(); p1 ---- (1 row) 步骤 4 查询t1表数据。 openGauss=# select * from t1; id | name ----+------ 1 | 李明 步骤 5 删除存储过程。 openGauss=# DROP PROCEDURE p1; DROP PROCEDURE带参数的存储过程步骤 1 创建一个带参数的存储过程,功能是计算输入两个参数相乘,输出计算结果。 openGauss=# CREATE OR REPLACE PROCEDURE p2 ( param1 IN INTEGER, param2 IN OUT INTEGER ) AS BEGIN param2:= param1 * param2; RAISE INFO 'param2 is: %', param2; END; / CREATE PROCEDURE 步骤 2 调用存储过程p2。 openGauss=# call p2(6,7); INFO: param2 is: 42 param2 -------- 42 (1 row)匿名块匿名块一般用于不频繁执行的脚本或不重复进行的活动。它们在一个会话中执行,并不被存储。以上是一个匿名块,与此相对的是命名块(也就是存储过程和函数)。其中,DO 语句用于执行匿名块;我们定义了一个字符串变量 name,然后给它赋值并输出一个信息;RAISE NOTICE 用于输出通知消息。openGauss=# DO $$ DECLARE name text; BEGIN name := 'PL/SQL'; RAISE NOTICE 'Hello %!', name; END $$; NOTICE: Hello PL/SQL! ANONYMOUS BLOCK EXECUTE嵌套子块PL/SQL 支持代码块的嵌套,也就是将一个代码块嵌入其他代码块的主体中。被嵌套的代 码块被称为子块(subblock),包含子块的代码块被称为外部块(subblock)。子块可以将代码 进行逻辑上的拆分,子块中可以定义与外部块重名的变量,而且在子块内拥有更高的优先级。openGauss=# DO $$ DECLARE name text; BEGIN name := 'outer_block'; RAISE NOTICE 'This is %', name; DECLARE name text := 'sub_block'; BEGIN RAISE NOTICE 'This is %', name; RAISE NOTICE 'The name FROM the outer block is %',name; END; RAISE NOTICE 'This is %', name; END $$; NOTICE: This is outer_block NOTICE: This is sub_block NOTICE: The name FROM the outer block is sub_block NOTICE: This is outer_block ANONYMOUS BLOCK EXECUTE条件语句条件语句的主要作用是判断参数或者语句是否满足已给定的条件,根据判定结果执行相应的操作。IF_THEN语句是IF的最简单形式。如果条件为真,statements将被执行。否则,将忽略它们的结果使该IF_THEN语句执行结束。IF_THEN_ELSE语句增加了ELSE的分支,可以声明在条件为假的时候执行的语句。IF_THEN_ELSE 语句可以嵌套。IF_THEN_ELSE语句增加了ELSE的分支,可以声明在条件为假的时候执行的语句# 通过IF_THEN_ELSIF_ELSE比较两个数的大小 openGauss=# DO $$ DECLARE i integer := 4; j integer := 5; BEGIN IF i > j THEN RAISE NOTICE 'i 大于 j'; ELSIF i < j THEN RAISE NOTICE 'i 小于 j'; ELSE RAISE NOTICE 'i 等于 j'; END IF; END $$; ENDNOTICE: i 小于 j ANONYMOUS BLOCK EXECUTECASE 语句简单 CASE 语句简单 CASE 语句只能进行简单的等值比较。依次判断每个 WHEN 之后的表达式,如果为真则执行相应的语句,后续的分支不再进行判断。openGauss=#CREATE OR REPLACE PROCEDURE proc_case_branch(pi_result in integer, pi_return out integer) AS BEGIN CASE pi_result WHEN 1 THEN pi_return := 111; WHEN 2 THEN pi_return := 222; WHEN 3 THEN pi_return := 333; WHEN 6 THEN pi_return := 444; END CASE; raise info 'pi_return : %',pi_return ; END; / test=> call proc_case_branch(3,0); INFO: pi_return : 333 pi_return ----------- 333 (1 row)搜索CASE语句语句可以实现更复杂的控制逻辑。依次判断每个 WHEN 之后的表达式,如果为真则执行相应的语句,后续的分支不再进行判断,如果没有匹配的值,执行ELSE语句openGauss=# DO $$ DECLARE i integer := 3; BEGIN CASE WHEN i BETWEEN 1 AND 5 THEN RAISE NOTICE '数据在1~5之间'; WHEN i BETWEEN 6 AND 10 THEN RAISE NOTICE '数据在6~10之间'; ELSE RAISE NOTICE 'other value'; END CASE; END $$; NOTICE: 数据在1~5之间 ANONYMOUS BLOCK EXECUTE循环语句LOOP语句该循环需要结合EXIT使用,否则将陷入死循环。以下存储过程,初始值i是0,loop语句持续循环,直到i累加到8后退出循环。openGauss=# DO $$ DECLARE i integer := 0; BEGIN LOOP EXIT WHEN i = 8; i := i + 1; RAISE NOTICE 'Loop: %', i; END LOOP; END $$; NOTICE: Loop: 1 NOTICE: Loop: 2 NOTICE: Loop: 3 NOTICE: Loop: 4 NOTICE: Loop: 5 NOTICE: Loop: 6 NOTICE: Loop: 7 NOTICE: Loop: 8 ANONYMOUS BLOCK EXECUTELoop语句结合CONTINUE,直接进入下一次循环。以下储存过程表示,当i对2取余为1就跳过执行下一次loop,不为1就输出。openGauss=# DO $$ DECLARE i integer := 0; BEGIN LOOP EXIT WHEN i = 8; i := i + 1; CONTINUE WHEN mod(i, 2) = 1; RAISE NOTICE 'Loop: %', i; END LOOP; END $$; NOTICE: Loop: 2 NOTICE: Loop: 4 NOTICE: Loop: 6 NOTICE: Loop: 8 NOTICE: Loop: 10 ANONYMOUS BLOCK EXECUTE for 语句for语句将i取值遍历从1到5,然后循环输出结果。 openGauss=# DO $$ BEGIN FOR i IN 1..6 LOOP RAISE NOTICE '输出结果为: %', i; END LOOP; END $$; NOTICE: 输出结果为: 1 NOTICE: 输出结果为: 2 NOTICE: 输出结果为: 3 NOTICE: 输出结果为: 4 NOTICE: 输出结果为: 5 NOTICE: 输出结果为: 6 ANONYMOUS BLOCK EXECUTE for语句用来遍数据表历查询结果。 openGauss=# DO $$ DECLARE e record; BEGIN FOR e IN (SELECT * FROM employees LIMIT 5) LOOP RAISE NOTICE 'Loop: %,%', e.first_name, e.last_name; END LOOP; END $$; NOTICE: Loop: Neena,Kochhar NOTICE: Loop: Ismael,Sciarra NOTICE: Loop: Luis,Popp NOTICE: Loop: Den,Raphaely NOTICE: Loop: David,Austin ANONYMOUS BLOCK EXECUTE 错误捕获默认情况下,存储过程遇到错误时会终止代码执行,同时撤销事务。在代码块中使用EXCEPTION捕获错误并继续事务。如果代码执行出错,程序将会进入 EXCEPTION 模块。openGauss=# CREATE OR REPLACE PROCEDURE proc_exp() AS DECLARE x INT :=0; y INT; BEGIN UPDATE employees SET first_name = 'James' WHERE first_name = 'John'; x := x + 1; y := x / 0; EXCEPTION WHEN division_by_zero THEN RAISE NOTICE 'caught division_by_zero'; RAISE NOTICE 'x: %',x; RETURN ; END; / CREATE PROCEDURE openGauss=# call proc_exp(); NOTICE: caught division_by_zero NOTICE: x: 1触发器触发器会在指定的数据库事件发生时自动执行函数。触发器函数与普通函数的区别在于它没有参数,并且返回类型为 trigger。FOR EACH ROW 表示行级触发器,FOR EACH STATEMENT 表示语句级触发器。NEW 类型为 RECORD,代表了行级触发器 INSERT、UPDATE 操作之后的新数据行。OLD类型为 RECORD,代表了行级触发器 UPDATE、DELETE 操作之前的旧数据行。event 可以是 INSERT、UPDATE、DELETE ,UPDATE 支持特定字段(UPDATE OF col1, clo2)的更新操作,触发器可以在事件之前(BEFORE)或者之后(AFTER)触发。步骤 1 创建表employees_history。 CREATE TABLE employees_history ( employee_id integer NOT NULL, /*员工编号,主键*/ first_name VARCHAR(20), /*名字*/ last_name VARCHAR(25) NOT NULL, /*姓氏*/ hire_date timestamp(0) without time zone NOT NULL, /*入职日期*/ salary numeric(8,2), /*月薪*/ department_id integer, /*部门编号*/ action_type varchar(10) not null, /*操作类型*/ change_dt timestamp not null,/*操作时间*/ CONSTRAINT emp_salary_min CHECK (salary > (0)) ); 步骤 2 创建触发器函数,修改employees表数据前将旧的数据插入到employees_history表中。 openGauss=# create or replace function employees_update_change() returns trigger as $$ begin INSERT INTO employees_history (employee_id, first_name, last_name, hire_date,salary,department_id, action_type, change_dt) values (old.employee_id, old.first_name, old.last_name, old.hire_date, old.salary,old.department_id, 'UPDATE', current_timestamp); RETURN new; end; $$ language plpgsql; 步骤 3 创建触发器,调用触发器函数employees_update_change()。 openGauss=# create trigger trg_employees_change before UPDATE on employees for each row execute PROCEDURE employees_update_change(); 步骤 4 修改employees表中employee_id为145的员工薪资salary修改为10。 openGauss=# select * from employees; employee_id | first_name | last_name | hire_date | salary | department_id --------------------+----------------+-----------------+---------------------- ----------+----------+--------------- 101 | Neena | Kochhar | 2005-09-21 00:00:00 | 17000.00 | 90 111 | Ismael | Sciarra | 2005-09-30 00:00:00 | 7700.00 | 100 113 | Luis | Popp | 2007-12-07 00:00:00 | 6900.00 | 100 114 | Den | Raphaely | 2002-12-07 00:00:00 | 11000.00 | 30 105 | David | Austin | 2005-06-25 00:00:00 | 4800.00 | 60 106 | Valli | Pataballa | 2006-02-05 00:00:00 | 4800.00 | 60 117 | Sigal | Tobias | 2005-07-24 00:00:00 | 2800.00 | 30 185 | Alexis | Bull | 2005-02-20 00:00:00 | 4100.00 | 50 186 | Julia | Dellinger | 2006-06-24 00:00:00 | 3400.00 | 50 145 | John | Russell | 2004-10-01 00:00:00 | 14000.00 | 80 openGauss=# update employees set salary=10 where employee_id=145; UPDATE 1 步骤 5 查看employees表,薪资salary已经由14000修改成了10。 openGauss=# select * from employees; employee_id | first_name | last_name | hire_date | salary | department_id --------------------+----------------+----------------------+--------------------------------+-------------- +-------------------- 101 | Neena | Kochhar | 2005-09-21 00:00:00 | 17000.00 | 90 111 | Ismael | Sciarra | 2005-09-30 00:00:00 | 7700.00 | 100 113 | Luis | Popp | 2007-12-07 00:00:00 | 6900.00 | 100 114 | Den | Raphaely | 2002-12-07 00:00:00 | 11000.00 | 30 105 | David | Austin | 2005-06-25 00:00:00 | 4800.00 | 60 106 | Valli | Pataballa | 2006-02-05 00:00:00 | 4800.00 | 60 117 | Sigal | Tobias | 2005-07-24 00:00:00 | 2800.00 | 30 185 | Alexis | Bull | 2005-02-20 00:00:00 | 4100.00 | 50 186 | Julia | Dellinger | 2006-06-24 00:00:00 | 3400.00 | 50 145 | John | Russell | 2004-10-01 00:00:00 | 10.00 | 80 步骤 6 查看employees_history表保留了修改前的值得 openGauss=# select * from employees_history; employee_id | first_name| last_name | hire_date | salary | department_id | action_type | change_dt -------------------+--------------- +---------------+-----------------------------+-------------+------+-------------+---------------------------- 145 | John | Russell | 2004-10-01 00:00:00 | 14000.00 | 80 | UPDATE | 2023-10-16 11:36:33.22553
  • [技术干货] opengauss数据库联系sql语句
    模拟题一检索客户信息以及其银行卡详细信息:SELECT c.*, bc.* FROM client c JOIN bank_card bc ON c.c_id = bc.b_c_id;列出所有理财产品的名称和描述:SELECT p_name, p_description FROM finances_product;查找购买保险且保额大于3000的客户:SELECT c.* FROM client c JOIN insurance i ON c.c_id = i.i_id WHERE i_amount > 3000;检索由基金经理ID为1管理的基金名称:SELECT f_name FROM fund WHERE f_manager = 1;列出具有其客户名称和购买时间的属性,其中属性状态为“可用”:SELECT c.c_name, p.* FROM client c JOIN property p ON c.c_id = p.pro_c_id WHERE pro_status = '可用';计算每个客户的银行卡数量:SELECT c.c_name, COUNT(bc.b_number) AS card_count FROM client c LEFT JOIN bank_card bc ON c.c_id = bc.b_c_id GROUP BY c.c_id, c.c_name;计算每个风险级别的金总额:SELECT risk_level, SUM(f_amount) AS total_funds FROM fund GROUP BY risk_level;查找既有信用卡又有储蓄卡的客户:SELECT c.* FROM client c JOIN bank_card bc_credit ON c.c_id = bc_credit.b_c_id AND bc_credit.b_type = '信用卡' JOIN bank_card bc_savings ON c.c_id = bc_savings.b_c_id AND bc_savings.b_type = '储蓄卡';检索总产业收入最高的前3位客户:SELECT c.c_name, SUM(p.pro_income) AS total_income FROM client c JOIN property p ON c.c_id = p.pro_c_id GROUP BY c.c_id, c.c_name ORDER BY total_income DESC LIMIT 3;列出每个保险项目以及每个项目的总保险金额:SELECT i_project, SUM(i_amount) AS total_insured_amount FROM insurance GROUP BY i_project;模拟题二找出每个风险级别下基金金额最大的基金名称及其金额:SELECT f.risk_level, f.f_name, f.f_amount FROM fund f WHERE f.f_amount = (SELECT MAX(f_amount) FROM fund WHERE risk_level = f.risk_level);列出购买理财产品金额最高的前两位客户及其购买金额:SELECT c.c_name, SUM(fp.p_amount) AS total_purchase_amount FROM client c JOIN bank_card bc ON c.c_id = bc.b_c_id JOIN finances_product fp ON bc.b_number = fp.p_id GROUP BY c.c_id, c.c_name ORDER BY total_purchase_amount DESC LIMIT 2;查找购买了所有不同类型保险的客户:SELECT c.c_name FROM client c WHERE NOT EXISTS ( SELECT DISTINCT i_type FROM insurance WHERE i_person = c.c_id EXCEPT SELECT DISTINCT i_type FROM insurance );计算每个客户的总资产(银行卡余额 + 理财产品金额 + 财产金额):SELECT c.c_name, COALESCE(SUM(bc.b_amount), 0) + COALESCE(SUM(fp.p_amount), 0) + COALESCE(SUM(p.pro_income), 0) AS total_assets FROM client c LEFT JOIN bank_card bc ON c.c_id = bc.b_c_id LEFT JOIN finances_product fp ON c.c_id = fp.p_id LEFT JOIN property p ON c.c_id = p.pro_c_id GROUP BY c.c_id, c.c_name;找出购买了所有类型理财产品的客户:SELECT c.c_name FROM client c WHERE NOT EXISTS ( SELECT DISTINCT fp_type FROM finances_product EXCEPT SELECT DISTINCT fp_type FROM finances_product fp WHERE c.c_id = fp.p_id );模拟题三找出每个风险级别下基金金额排名第二的基金名称及其金额:SELECT f.risk_level, f.f_name, f.f_amount FROM fund f WHERE f.f_amount = ( SELECT MAX(f_amount) FROM fund WHERE risk_level = f.risk_level AND f_id NOT IN ( SELECT f_id FROM fund WHERE risk_level = f.risk_level ORDER BY f_amount DESC LIMIT 1 ) );列出每个客户的总理财产品金额和保险金额,按总金额降序排列:SELECT c.c_name, COALESCE(SUM(fp.p_amount), 0) AS total_finances_amount, COALESCE(SUM(i.i_amount), 0) AS total_insurance_amount, COALESCE(SUM(fp.p_amount), 0) + COALESCE(SUM(i.i_amount), 0) AS total_amount FROM client c LEFT JOIN bank_card bc ON c.c_id = bc.b_c_id LEFT JOIN finances_product fp ON bc.b_number = fp.p_id LEFT JOIN insurance i ON c.c_id = i.i_person GROUP BY c.c_id, c.c_name ORDER BY total_amount DESC;找出每个客户购买最多数量的理财产品类型:SELECT c.c_name, fp.p_type FROM client c LEFT JOIN bank_card bc ON c.c_id = bc.b_c_id LEFT JOIN finances_product fp ON bc.b_number = fp.p_id WHERE fp.p_id = ( SELECT p_id FROM finances_product WHERE p_type = fp.p_type ORDER BY COUNT(*) DESC LIMIT 1 );计算每种类型理财产品的平均年收益,并按平均年收益降序排列:SELECT p_type, AVG(p_year) AS avg_yearly_return FROM finances_product GROUP BY p_type ORDER BY avg_yearly_return DESC;查找每个客户购买理财产品的时间距今最近的一次,并列出客户名称、产品名称和购买时间:SELECT c.c_name, fp.p_name, MAX(fp.purchase_time) AS latest_purchase_time FROM client c LEFT JOIN bank_card bc ON c.c_id = bc.b_c_id LEFT JOIN finances_product fp ON bc.b_number = fp.p_id GROUP BY c.c_id, c.c_name, fp.p_name;模拟题四找出每位客户累计购买理财产品金额最高的前两个月份,包括客户名称、月份和总金额:SELECT c.c_name, EXTRACT(MONTH FROM fp.purchase_time) AS purchase_month, SUM(fp.p_amount) AS total_purchase_amount FROM client c LEFT JOIN bank_card bc ON c.c_id = bc.b_c_id LEFT JOIN finances_product fp ON bc.b_number = fp.p_id GROUP BY c.c_id, c.c_name, EXTRACT(MONTH FROM fp.purchase_time) ORDER BY c.c_name, purchase_month, total_purchase_amount DESC;计算每位客户购买理财产品的总金额,但只包括购买时间在客户注册后的数据:SELECT c.c_name, SUM(fp.p_amount) AS total_purchase_amount FROM client c LEFT JOIN bank_card bc ON c.c_id = bc.b_c_id LEFT JOIN finances_product fp ON bc.b_number = fp.p_id AND fp.purchase_time >= c.register_time GROUP BY c.c_id, c.c_name;找出每位客户至今为止购买了所有理财产品类型的客户:SELECT c.c_name FROM client c WHERE NOT EXISTS ( SELECT DISTINCT p_type FROM finances_product EXCEPT SELECT DISTINCT p_type FROM finances_product fp WHERE c.c_id = fp.p_id );列出每位客户最近一次购买理财产品的详细信息,包括客户名称、产品名称和购买时间:SELECT c.c_name, fp.p_name, fp.purchase_time FROM client c LEFT JOIN bank_card bc ON c.c_id = bc.b_c_id LEFT JOIN finances_product fp ON bc.b_number = fp.p_id WHERE fp.purchase_time = ( SELECT MAX(purchase_time) FROM finances_product WHERE p_id = bc.b_number );找出购买了所有类型保险的客户及其保险类型:SELECT c.c_name, i.i_type FROM client c CROSS JOIN ( SELECT DISTINCT i_type FROM insurance ) i WHERE NOT EXISTS ( SELECT DISTINCT i_type FROM insurance EXCEPT SELECT DISTINCT i_type FROM insurance ii WHERE ii.i_person = c.c_id );
  • [技术干货] opengauss 常用工具
    数据的导入导出gs_dump是openGauss用于导出数据库相关信息的工具,用户可以自定义导出一个数据库或其中的对象(模式、表、视图等)。支持导出的数据库可以是默认数据库postgres,也可以是自定义数据库准备数据# 使用omm用户,创建备份目录 [omm@opengauss]$ mkdir /gaussdb/backup [omm@opengauss]$ cd /gaussdb/backup # 登录数据库 gsql -d postgres -p 26000 -r # 创建customer_t1表 drop table if exists customer_t1; NOTICE: table "customer_t1" does not exist, skipping DROP TABLE # if exists 如果表存在删除表如果不存在返回此表不存在且不会产生错误 postgres=# CREATE TABLE customer_t1 postgres-# ( postgres(# c_customer_sk integer, postgres(# c_customer_id char(5), postgres(# c_first_name char(6), postgres(# c_last_name char(8) postgres(# ); CREATE TABLE # 向表中插入数据 postgres=# INSERT INTO customer_t1 (c_customer_sk, c_customer_id, c_first_name) VALUES postgres-# (3769, 'hello', DEFAULT) , postgres-# (6885, 'maps', 'Joes'), postgres-# (4321, 'tpcds', 'Lily'), postgres-# (9527, 'world', 'James'); INSERT 0 4 postgres=# INSERT 0 4 # 查看表中数据 postgres=# select * from customer_t1; c_customer_sk | c_customer_id | c_first_name | c_last_name ---------------+---------------+--------------+------------- 3769 | hello | | 6885 | maps | Joes | 4321 | tpcds | Lily | 9527 | world | James | (4 rows) # 创建joe用户 postgres=# drop user if exists joe; NOTICE: role "joe" does not exist, skipping DROP ROLE postgres=# postgres=# CREATE USER joe WITH PASSWORD "Bigdata@123"; CREATE ROLE # 在joe用户下创建表mytable postgres=# \q [omm@ opengauss ~]$ gsql -d postgres -U joe -W Bigdata@123 -p 26000 -r gsql ((openGauss 2.0.0 build 78689da9) compiled at 2021-03-31 21:03:52 commit 0 last mr ) Non-SSL connection (SSL connection is recommended when requiring high-security) Type "help" for help. postgres=> drop table if exists mytable; DROP TABLE postgres=> CREATE TABLE mytable (firstcol int); CREATE TABLE # 向mytable表插入数据。 postgres=> INSERT INTO mytable values (100); INSERT 0 1 # 查看mytable文件 postgres=> SELECT * from mytable; firstcol ---------- 100 (1 row) # 查看当前表信息 postgres=> \d List of relations Schema | Name | Type | Owner | Storage --------+-------------+-------+-------+---------------------------------- joe | mytable | table | joe | {orientation=row,compression=no} public | customer_t1 | table | | {orientation=row,compression=no} (2 rows)copy数据导出copy 命令需要在数据库中进行操作copy 命令导出的数据直接是数据源表postgres=> \c - omm # 需要输入密码 且自己的默认用户不一定是omm c (CONNECT) 允许用户连接到指定数据库 # 使用copy命令进行导出 copy 表名 to ‘位置和名称’ delimiter ‘分隔符’; copy customer_t1 to '/gaussdb/backup/copy_cost.txt' delimiter '^'; # delimiter 分隔符 COPY 4 # 显示拷贝的数据量 # 查看导出文件 在宿主机 omm 用户 cat copy_cost.txt 3769^hello^\N^\N 6885^maps ^Joes ^\N 4321^tpcds^Lily ^\N 9527^world^James ^\Ngs_dump 数据导出gs_dump 导出的将是sql语句。 omm用户导出使用gs_dump命令将postgres数据库导出,导出为纯文本格式。gs_dump部分重要指令解释:-f:将导出文件发送至指定目录文件夹。-F:选择导出文件格式。-F参数值如下:p:纯文本格式c:自定义归档 # 自定义customd:目录归档格式t:tar归档格式-n:只导出与模式名称匹配的模式,此选项包括模式本身和所有它包含的对象。-t:指定导出的表(或视图、序列、外表),可以使用多个-t选项来选择多个表,也可以使用通配符指定多个表对象。-T:不转储的表(或视图、或序列、或外表)对象列表,可以使用多个-T选项来选择多个表,也可以使用通配符指定多个表对象。-a: 导出所有数据(包括那些被删除或已修改的数据)。--data-only: 只导出数据,不包含表结构。# 导出omm 用户的数据到/gaussdb/backup/gsdump_post.sql中导出格式为纯文本 gs_dump -U 用户 -W 密码 -f 导出文件位置和名称 -p 端口号 -F 导出格式 示例: gs_dump -U omm -W Bigdata@123 -f /gaussdb/backup/gsdump_post.sql -p 7654 -F p # 使用gs_dump,导出postgres数据库,导出为tar格式。 gs_dump -U omm -W Bigdata@123 -f /gaussdb/backup/gsdump_post.tar -p 7654 -F t # 导出指定数据表 gs_dump -p 15400 -f /home/omm/backup/2.sql school -t 模式.course -a --data-only -F p使用gs_dump导出依赖于表的视图# 连接数据库,并创建依赖于表customer_t1的视图vw_customer_t1,后退出。 gsql -d postgres -p 26000 –r create view vw_customer_t1 as select * from customer_t1 limit 2; \q # 导出依赖于表customer_t1的视图vw_customer_t1 gs_dump -s -p 26000 postgres -t PUBLIC.customer_t1 --include-depend-objs --exclude-self -f /gaussdb/backup/view_cust.sql -F p # -s 表示生成的sql脚本仅仅包含数据库对象的结构(即模式,表,试图等),而不包含数据 # -t PUBLIC.customer_t1 指定要备份的表的名称,位于public模式中 # --exclude-self 表示不包括指定表自身的定义和数据 # -f 指定输出文件的路径 # -F p 指定生成备份文件的格式 p纯文本格式gs_dumpall 数据导出在omm用户下进行的gs_dumpall是openGauss用于导出所有数据库相关信息工具,它可以导出openGauss数据库的所有数据,包括默认数据库postgres的数据、自定义数据库的数据、以及openGauss所有数据库公共的全局对象。gs_dumpall在导出openGauss所有数据库时分为两部分:gs_dumpall自身对所有数据库公共的全局对象进行导出,包括有关数据库用户和组,表空间以及属性(例如,适用于数据库整体的访问权限)信息。s_dumpall通过调用gs_dump来完成openGauss中各数据库的SQL脚本文件导出,该脚本文件包含将数据库恢复为其保存时的状态所需要的全部SQL语句。以上两部分导出的结果为纯文本格式的SQL脚本文件,使用gsql运行该脚本文件可以恢复openGauss数据库使用gs_dumpall一次导出openGauss的所有数据库。gs_dumpall -f /gaussdb/backup/gsdumpall.sql -p 26000gsql 数据导入对于.sql文件,可使用gsql直接导入。 在omm用户# 步骤 1删除之前导出的表。 gsql -p 26000 postgres -r drop table joe.mytable; drop table public.customer_t1 cascade; # cascade 级联 \q # 步骤 2使用gsql将导出的表恢复。(出现ERROR: schema "joe" already exists报错可忽略) gsql -p 26000 postgres -r -f /gaussdb/backup/gsdump_post.sql # 查看恢复后的表 gsql -p 26000 postgres -r select * from public.customer_t1;copy 命令导入对于使用copy导出的数据,同样可以使用copy导入。# 删除使用copy命令导出过的表 gsql -p 26000 postgres -r truncate table public.customer_t1; # truncate table 表名 删除表中全部数据 # 使用copy命令进行导入 copy customer_t1 from '/gaussdb/backup/copy_cost.txt' delimiter '^'; # 查看导入的表数据。 select * from customer_t1;gs_restore 数据导入gs_restore是openGauss提供的针对gs_dump导出数据的导入工具。通过此工具可由gs_dump生成的导出文件进行导入。gs_restore工具由操作系统用户omm执行。-d 连接数据库dbname 并直接将数据导入到该数据库中-s 只导入模式定义,不导入数据,当前的序列值也不会被导入-e 当发送SQL语句到数据库时如果出现错误,则退出。默认状态下会忽略错误任务并继续执行导入,且在导入后会显示一系列错误信息。-c 在重新创建数据库对象前,清理(删除)已存在于将要导入的数据库中的数据库对象。# 删除使用gs_dump导出的表和视图。 gsql -p 26000 postgres -r drop table joe.mytable; drop table public.customer_t1; # 使用gs_restore导入gsdump_post.tar文件内数据到tpcc数据库。 新建tpcc数据库 create database tpcc; \q 导入gsdump_post.tar文件内数据到tpcc数据库。 gs_restore /gaussdb/backup/gsdump_post.tar -p 26000 -d tpcc # -d 指定数据库 # 登录tpcc数据库查看恢复的数据。 gsql -p 26000 tpcc -r select * from public.customer_t1; select * from joe.mytable; \qgs_basebackup 备份工具gs_basebackup 的实现目标是对服务器数据库文件的二进制进行拷贝实现原理使用了复制协议当前支持热备份模式和压缩格式备份。gs_basebackup仅支持全量备份,不支持增量清理实验环境# 删除创建的数据库及用户 gsql -p 26000 postgres -r \l drop database tpcc; \du drop user joe; \q假设有以下操作:​ a. 创建表customer_t1,并导入4条数据;​ b. 创建依赖于表customer_t1的视图vw_customer_t1;​ create view vw_customer_t1 as select * from customer_t1 limit 2;​ 此时查看视图vw_customer_t1,显示2条数据。​ c. 导出依赖于表customer_t1的视图vw_customer_t1到文件vw_customer.sql;​ d. 重命名表customer_t1为customer_t1_bak;​ e. 新建表customer_t1,不插入数据;​ f. 导入vw_customer.sql;请问此时查看视图vw_customer,显示有几条数据?参考答案:视图vw_customer中无数据解释:在opengauss中重命名表会导致相关视图失效,因为视图引用的表已经不再存在,除非你手动更新视图的定义在这个情况下,由于表 customer_t1 被重命名为 customer_t1_bak,视图 vw_customer_t1 将失效,因为它引用的表已经不再存在。因此,在这种情况下,查看视图 vw_customer_t1 是不会显示数据的,因为这个视图无法正常工作尝试使用COPY的方式导出查询结果数据集(即where条件语句)将数据库查询结果导出csv# 命令: COPY { table_name [ ( column_name [, ...] ) ] | ( query) } TO { 'filename' | PROGRAM 'command' | STDOUT } [ [ WITH ] (option [, ...] ) ] # 示例: COPY user TO '/tmp/data/test.csv' WITH csv; # 导出指定的属性: COPY user(name,password) TO '/tmp/data/test.csv' WITH csv; # 使用select 语句: COPY (select * from user where id=) TO '/tmp/data/test.csv' WITH csv; # 指定要导出哪些字段: COPY (select name,age from user) TO '/tmp/data/test.csv'WITH csv header; 将文件导入到表中(导入csv)# 命令: COPY table_name [ ( column_name [, ...] ) ] FROM { 'filename' | PROGRAM 'command' | STDIN } [ [ WITH ] ( option [, ...] ) ] # 示例:导入命令基本与导出一样,只是将TO 改为 FROM COPY user_1 FROM '/tmp/data/test.csv' WITH csv; # 如果导出的时候,指定了header属性,那么在导入的时候,也需要指定: COPY user_1(name, age) FROM '/tmp/data/test.csv' WITH csv header;gs_postuninstall 一键式环境清理 仅能root用户使用
  • [技术干货] openGauss资源池化
    Q1:什么是资源池化?A1:资源池化是一种新型的数据库HA架构,基于磁阵设备提供主备机共享一份存储的能力,解决传统HA部署下存储容量较单机翻倍的问题,同时备机支持实时一致性读。Q2:为什么要了解资源池化?A2:资源池化架构解决了传统架构要在性能和可靠性之间做取舍和以硬件数量换取性能和可靠性的“不可能三角”,数据库全栈能力有较大提升:一、可靠性方面,通过共享磁盘技术大幅缩短计算实例故障恢复时间;二、资源利用率方面,不再需要存算捆绑,实现计算存储资源按需配置,计算资源利用率提高33%以上,存储利用率提高50%以上;三、性能方面,不再需要牺牲性能来满足可靠性要求,典型场景下性能提升1.6倍。Q3:资源池化是如何实现的?A3:资源池化包含计算池化、存储池化和内存池化,通过软硬协同,全栈优化,最终实现全栈可观测、可跟踪、开箱性能即最佳的资源池化架构。在计算池化方面,资源池化可以进行多样化算力的优化,包括传统的X86、鲲鹏等算力,使用最合适的数据库引擎去满足不同应用的数据处理诉求;在存储池化方面,不仅支持多种存储,实现NDP算子卸载,还可以支持DPU硬件加速,支持NoF新型存储访问协议;在内存池化方面,实现计算节点间内存互联,支持RDMA高速访问,打造了一个透明的跨节点内存池。Q4:资源池化生产场景所需要的环境?A4:两台及以上的物理机,一台企业级集中式存储(比如Huawei Dorado系列)或支持iscsi3协议的集中式存储,且需要支持SCSI3的PR协议和CAW协议。两台物理机和存储之间通过光交换机互连,两台物理机之间通过光交换机或以太交换机互连,业务客户端和物理机之间通过光交换机或以太交换机互连。Q5:什么是资源池化开发者环境?A5:资源池化开发者可以用于开发调试的环境,不需要磁阵设备和物理机就可以完成搭建。搭建方式详见https://docs-opengauss.osinfra.cn/zh/docs/latest/docs/DatabaseAdministrationGuide/%E8%B5%84%E6%BA%90%E6%B1%A0%E5%8C%96%E5%BC%80%E5%8F%91%E8%80%85%E7%8E%AF%E5%A2%83%E9%83%A8%E7%BD%B2.htmlQ6:资源池化架构是什么样的?A6:资源池化架构可以参考下图:​Q7:资源池化中如何充分利用备机实时一致性读能力?A7:可以通过多机并行能力,在备机实时一致性读能力的基础上,大幅提高资源池化集群OLAP性能。在该能力下,任意节点发起的读请求会根据代价和规则决定采用多机查询或者原生单机查询,多机查询时会将多机执行计划分发到各节点执行,再由查询节点汇聚各节点数据实现所有读节点并行查询,充分发挥集群的OLAP能力。与openGauss传统架构相比,资源池化架构在TPC-H场景下,整体性能提升2.58倍。Q8:资源池化中的DSS组件的作用是什么?A8:通过共享存储和共享内存,DSS(分布式存储服务)实现了跨节点管理文件,目录,卷和卷组及其元数据。 Q9:资源池化中的DMS组件的作用是什么? A9:计算节点通过DMS(分布式内存服务)实现内存中缓存页面的实时交换共享,通过DMS的分布式锁服务实现全局数据结构的读写操作,并对外提供一写多读服务。Q10:资源池化中的CM的作用是什么?A10:集群管理(CM)是一款集群资源管理软件自定义资源监控提供数据库状态监控,网络通信故障监控,文件系统故障监控,故障后数据库自动主备切换等能力。转自:https://www.hikunpeng.com/forum/thread-0219141555413504021-1-1.html
  • [技术解读] OpenGauss执行计划代价估算
     OpenGauss支持通过代价估算进行执行计划的调优,代价分为IO 代价和CPU代价,这两个代价都和处理的元组数量正相关;IO代价SeqScan:IO代价为:表数据页总数x seq_page_cost(或者default_ seq_page_cost)IndexScan:IO代价为P* random_page_cost(default_ random_page_cost);其中P是满足数据的页数量,常常通过R(表元组总数x选择率)估算,其中选择率=满足约束的记录数/总记录数,选择率可以通过前面提到的统计信息完成估算CPU代价元组处理代价:将一条磁盘数据转换为元组形式的代价;通过cpu_tuple_cost和cpu_index_tuple_cost表示对普通数据和索引数据的代价数据操作代价:对元组进行投影,或者根据约束表达式判断元组是否满足条件的代价;通过cpu_operator_cost表征。
  • 三头六臂战力增倍--OpenGauss5.0.0一主两备扩容至一主三备
    三头六臂战力增倍--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命令执行成功,检查集群状态:至此,扩容过程已经完成。业务峰值的时候扩容,过峰之后自然会有扩容的诉求,关于缩容过程的介绍,将在下期进行,敬请关注。
  • [技术干货] openGauss---MOT特性及价值
    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%,远远领先其他行业数据库。这种能力在现代的多核服务器上尤为明显和重要。
  • [技术干货] openGauss3.1.1高可用——主备机
    主备机可获得性本特性自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(一主多备)等,使得实例故障后可以尽可能快地恢复,不中断业务,将因为硬件、软件和人为造成的故障对业务的影响降到最低,以保证业务的连续性。
  • [技术干货] openGauss-定时任务
    在一个固定的时间点活间隔一段时间需要频繁触发某一动作,为了使用便捷,有了定时任务,极大的减少了工作的重复性,提高了效率。定时任务的内容 基于定时任务产生的背景,定时任务内容包括:定时任务的创建、任务到达时间点自动执行、删除任务、任务内容的修改(任务 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) 删除定时任务
总条数:66 到第
上滑加载中