From 764a94f28be42a61dbf85b323bdfb13927ace1a1 Mon Sep 17 00:00:00 2001 From: wangshifei <18734596042@163.com> Date: Tue, 15 Oct 2024 02:57:25 +0000 Subject: [PATCH 01/13] =?UTF-8?q?=E6=96=B0=E5=BB=BA=20wangshifei?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/zh/blogs/wangshifei/.keep | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 app/zh/blogs/wangshifei/.keep diff --git a/app/zh/blogs/wangshifei/.keep b/app/zh/blogs/wangshifei/.keep new file mode 100644 index 00000000..e69de29b -- Gitee From 046967a9dec2000bc7b02850700c3775b78a8ee7 Mon Sep 17 00:00:00 2001 From: wangshifei <18734596042@163.com> Date: Tue, 15 Oct 2024 03:05:08 +0000 Subject: [PATCH 02/13] =?UTF-8?q?add=20app/zh/blogs/wangshifei/DBeaver?= =?UTF-8?q?=E8=BF=9C=E7=A8=8B=E8=BF=9E=E6=8E=A5openGauss=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E5=BA=93=E6=8A=A5=E9=94=99=E6=B1=87=E6=80=BB.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: wangshifei <18734596042@163.com> --- ...2\245\351\224\231\346\261\207\346\200\273" | 125 ++++++++++++++++++ 1 file changed, 125 insertions(+) create mode 100644 "app/zh/blogs/wangshifei/DBeaver\350\277\234\347\250\213\350\277\236\346\216\245openGauss\346\225\260\346\215\256\345\272\223\346\212\245\351\224\231\346\261\207\346\200\273" diff --git "a/app/zh/blogs/wangshifei/DBeaver\350\277\234\347\250\213\350\277\236\346\216\245openGauss\346\225\260\346\215\256\345\272\223\346\212\245\351\224\231\346\261\207\346\200\273" "b/app/zh/blogs/wangshifei/DBeaver\350\277\234\347\250\213\350\277\236\346\216\245openGauss\346\225\260\346\215\256\345\272\223\346\212\245\351\224\231\346\261\207\346\200\273" new file mode 100644 index 00000000..a29c7a94 --- /dev/null +++ "b/app/zh/blogs/wangshifei/DBeaver\350\277\234\347\250\213\350\277\236\346\216\245openGauss\346\225\260\346\215\256\345\272\223\346\212\245\351\224\231\346\261\207\346\200\273" @@ -0,0 +1,125 @@ +--- +title: '【第七届openGauss技术文章征集】DBeaver远程连接openGauss数据库报错汇总' +date: '2024-10-15' +category: 'blog' +tags: ['openGauss'] +archives: '2024-04' +author: '墨竹' +summary: 'Just about everything you'll need to style in the theme:headings, paragraphs, blockquotes, tables, code blocks, and more.' +--- + +# DBeaver远程连接openGauss数据库报错汇总 + +在openGauss 6.0.0版本正式上线后,在上手练习的过程就遇到Invalid username/password问题解决过程就用不少的时间来解决问题。因此就产生想按照PG配置习惯配置参数文件,看看会遇到哪些问题,顺便也整理测试过程中遇到的各种连接报错,以供初学者参考。 + +## Connection refused: connect + +``` +Connection to 192.168.181.20:15400 refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections. + Connection refused: connect +``` + +当客户端提示该报错,我们可以通过三个方向进行排查 + +1、查看防火墙状态,看是否关闭 + +2、查看客户端的IP、端口填写是否正确 + +3、查看postgresql.conf文件中listen_addresses是否配置 + +如果参数是已经注释的,可以取消注释并配置*或者主机IP;如果已经配置参数,则需要检查配置的IP是否正确 + +``` +--主机IP +listen_addresses = '192.168.181.20' +或 +listen_addresses = '*' +``` + +## The connection attempt failed + +``` +The connection attempt failed. + Connection reset +``` + +当客户端提示该报错,我们应该通过以下几点进行排查 + +1、pg_hba.conf中是否新增认证规则 + +2、pg_hba.conf中ADDRESS参数对应的IP和子网验证是否正确 + +``` +--这里的IP和子网掩码,如果设置的时候也需要注意。当子网掩码的位数为32时,IP需要设置为固定的IP。假如不小心设置为192.168.181.0/32就会报如上的错误。 +host all all 192.168.181.1/32 sha256 +--对于测试环境我们访问不做控制我们可以设置为 +host all all 0.0.0.0/0 sha256 +--也可以对整个网段进行设置 +host all all 192.168.181.0/24 sha256 +``` + +3、可能是参数配置后未生效导致,重启或者执行select pg_reload_conf()命令 + +## Invalid username/password + +``` +[192.168.181.1:62786/192.168.181.20:15400] FATAL: Invalid username/password,login denied. +``` + +当客户端报错提示Invalid username/password时,目前遇到的该问题有两种场景,分别是密码不正确和认证加密方式不一致。 + +### 密码不正确 + +这种情况应该是我们遇到该问题的时候,首先应该检查输入是否正确。如果在不确认密码是否正确的时候,建议可以先修改密码,然后再测试是否可以正确连接数据库。 + +``` +alter user test identified by 'openGauss@2024'; +``` + +### 认证加密方式配置是否正确 + +先查看openGauss数据库的参数password_encryption_type的值。 + +``` +show password_encryption_type; +``` + +在未修改数据库中该参数的时候,该参数默认为2,即表示采用sha256方式对密码加密。然后再查看pg_hba.conf中新增规则的METHOD参数,是否为sha256,如果参数文件中配置的是其他加密方式,比如md5,则有如下两种方法解决该问题 + +(1)、修改pg_hba.conf中加密方式为sha256 + +(2)、修改password_encryption_type的参数值为1或0,这个时候我们配置md5,其实也是可以适用。但是需要注意修改password_encryption_type参数的配置不会自动触发已有用户密码加密方式的修改,只会影响新创建用户或修改用户密码操作。所以我们需要在修改参数后并重启数据库使参数生效,然后还需要修改数据库用户口令。 + +``` +alter user test identified by 'openGauss@0430'; +``` + +该问题可以详细查看《DBeaver连接openGauss报错Invalid username/password问题排查》https://www.modb.pro/db/1784591381011976192文章中详细介绍。 + +## no pg_hba.conf entry for host + +``` +[192.168.181.1:64658/192.168.181.20:15400] FATAL: no pg_hba.conf entry for host "192.168.181.1", user "test", database "testdb", SSL off +``` + +当客户端提示该报错的时候,其实提示还是比较清晰的,检查一下pg_hba.conf中是否对数据库或用户做了限制。如果在配置文件中有对数据库和用户有限制,则检查配置是否正确或者是否新增对应访问控制规则。 + +## FATAL: database "testdb2" does not exist + +``` +[192.168.181.1:64924/192.168.181.20:15400] FATAL: database "testdb2" does not exist +``` + +这条信息说明尝试连接的数据库不存在,请检查连接的数据库名输入是否有误。 + +## Forbid remote connection with trust method! + +``` +[192.168.181.1:54091/192.168.181.20:15400] FATAL: Forbid remote connection with trust method! +``` + +采用这种认证模式时,openGauss只完全信任从服务器本机使用gsql且不指定-U参数的连接,此时不需要口令。设置文件系统权限只能Unix域套接字连接,它不会限制本地TCP/IP连接。为保证本地TCP/IP安全,**openGauss不允许远程连接使用trust认证方法** + +## 总结 + +上述报错都是最近测试并使用openGauss 6.0.0的过程遇到的问题,我也对这些报错逐个模拟并对解决办法进行详细的验证。同时受限于个人能力,给出的解决方法并不一定全面,请各位老师多多包涵。后续有其他新的问题或者同类型错误场景,再对文档进行补充完善。 \ No newline at end of file -- Gitee From 0b8a438769c9eb11263d95be58a225c5e06fb105 Mon Sep 17 00:00:00 2001 From: wangshifei <18734596042@163.com> Date: Tue, 15 Oct 2024 03:08:56 +0000 Subject: [PATCH 03/13] =?UTF-8?q?add=20app/zh/blogs/wangshifei/DBeaver?= =?UTF-8?q?=E8=BF=9E=E6=8E=A5openGauss=E6=8A=A5=E9=94=99Invalid=20username?= =?UTF-8?q?=20password=E9=97=AE=E9=A2=98=E6=8E=92=E6=9F=A5.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: wangshifei <18734596042@163.com> --- ...7\256\351\242\230\346\216\222\346\237\245" | 95 +++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 "app/zh/blogs/wangshifei/DBeaver\350\277\236\346\216\245openGauss\346\212\245\351\224\231Invalid username password\351\227\256\351\242\230\346\216\222\346\237\245" diff --git "a/app/zh/blogs/wangshifei/DBeaver\350\277\236\346\216\245openGauss\346\212\245\351\224\231Invalid username password\351\227\256\351\242\230\346\216\222\346\237\245" "b/app/zh/blogs/wangshifei/DBeaver\350\277\236\346\216\245openGauss\346\212\245\351\224\231Invalid username password\351\227\256\351\242\230\346\216\222\346\237\245" new file mode 100644 index 00000000..3c95ef2f --- /dev/null +++ "b/app/zh/blogs/wangshifei/DBeaver\350\277\236\346\216\245openGauss\346\212\245\351\224\231Invalid username password\351\227\256\351\242\230\346\216\222\346\237\245" @@ -0,0 +1,95 @@ +--- +title: '【第七届openGauss技术文章征集】DBeaver连接openGauss报错Invalid username/password问题排查' +date: '2024-10-15' +category: 'blog' +tags: ['openGauss'] +archives: '2024-04' +author: '墨竹' +summary: 'Just about everything you'll need to style in the theme:headings, paragraphs, blockquotes, tables, code blocks, and more.' +--- +# DBeaver连接openGauss报错Invalid username/password问题排查 + +## 问题现象 + +最近openGauss6.0版本发布后,也想练练手。但是安装成功后,使用DBeaver连接数据库时报如下错误 + +``` +[192.168.181.1:62786/192.168.181.20:15400] FATAL: Invalid username/password,login denied. +``` +![20240428_152338.jpg](https://oss-emcsprod-public.modb.pro/image/editor/20240429-5a7bccdf-290f-49ce-81ef-ba6dedfa8af9.jpg) +## 问题定位与分析 + +当客户端报错提示Invalid username/password时,根据目前已有的经验,大概率是黑白名单pg_hba.conf的配置文件配置不正确或者输入的密码错误。 + +### 密码不正确 + +这种情况应该是我们遇到该问题的时候,首先应该检查输入是否正确。如果在不确认密码是否正确的时候,建议可以先修改密码,然后再测试是否可以正确连接数据库。 + +``` +alter user test identified by 'openGauss@2024'; +``` + +### 配置文件的问题 + +当我们在上一步确认密码正确的情况,我们可以在服务器端通过gsql指定用户名密码连接验证,看是否可以正常连接数据库。 + +``` +[omm@openGauss dn]$ gsql -d testdb -p 15400 -Utest -WopenGauss@2024 +gsql ((openGauss 6.0.0-RC1 build ed7f8e37) compiled at 2024-03-31 11:59:31 commit 0 last mr ) +Non-SSL connection (SSL connection is recommended when requiring high-security) +Type "help" for help. + +testdb=> \q +``` + +当服务器端可以正常连接,但是客户端通过DBeaver客户端连接的时候报Invalid username/password时,这个时候我们再来查看pg_hba.conf配置文件中新增的内容,前四项都没有任何的限制,目前只能猜测加密方式的问题。其实当时自己心里也没底,当时自己受PG的经验认知,openGauss是用PG的内核,应该也支持md5加密吧。通过查看openGauss的文档,password_encryption_type参数决定了采用何种加密方式对用户密码进行加密存储。默认值为2,即表示模式采用sha256方式对密码加密。这个时候我们再查看pg_hba.conf中参数配置项,发现新增的一条规则的METHOD,配置的是md5。再对METHOD参数修改为sha256后,客户端可以正常连接了。 + +``` +host all all 0.0.0.0/0 sha256 +``` + +## 问题处理 + +当我们知道该问题的原因,那么解决问题就相当容易了,总结来说可以通过如下两种方式解决 + +### 修改pg_hba.conf配置文件 + +修改pg_hba.conf中之前新增规则中的METHOD的参数值为sha256,保持和password_encryption_type默认加密类型一致 + +``` +host all all 0.0.0.0/0 sha256 +``` + +### 修改password_encryption_type参数配置 + +我们可以修改password_encryption_type的参数值为1或0,这个时候我们配置md5,其实也是可以适用。 + +按照这个思路,修改password_encryption_type参数为1或0,且启动数据库后,由于未修改加密方式pg_hba.conf的METHOD参数,仍然为md5,执行reload命令使参数生效。 + +``` +gs_guc reload -D /data/openGauss/install/data/dn -c "password_encryption_type=0" +``` + +但是在客户端测试连接的时候,仍然报Invalid username/password错误。刚开始以为是bug的,但是经过查看password_encryption_type的参数介绍,当修改改参数的配置不会自动触发已有用户密码加密方式的修改,只会影响新创建用户或修改用户密码操作。所以我们需要执行修改数据库用户命令,同时会有如下的提示。 + +``` +openGauss=# alter user test identified by 'openGauss@0428'; +NOTICE: The encrypted password contains MD5 ciphertext, which is not secure. +ALTER ROLE +``` + +当我们再次通过DBeaver连接数据库,可以正常使用。 + +## 问题总结 + +问题虽然解决了,但是回顾产生问题的原因,是由于自己根据PG对的pg_hba.conf规则配置的经验认为,以为两者相差不大,所以在未查阅文档的情况,按照经验配置为了md5。在这里只想说有时经验真的不靠谱啊!另外在最后,我们看一下password_encryption_type的详细介绍: + +**参数说明:**该字段决定采用何种加密方式对用户密码进行加密存储。修改此参数的配置不会自动触发已有用户密码加密方式的修改,只会影响新创建用户或修改用户密码操作。 + +**取值范围:**0、1、2、3 + +- 0表示采用md5方式对密码加密。 +- 1表示采用sha256和md5两种方式分别对密码加密。 +- 2表示采用sha256方式对密码加密。 +- 3表示采用sm3方式对密码加密 + -- Gitee From 7b8d5fa42e11c6b3ae7ff8f72e3087a27940e9fb Mon Sep 17 00:00:00 2001 From: wangshifei <18734596042@163.com> Date: Tue, 15 Oct 2024 03:10:17 +0000 Subject: [PATCH 04/13] =?UTF-8?q?add=20app/zh/blogs/wangshifei/=E6=84=8F?= =?UTF-8?q?=E5=A4=96=E5=8F=91=E7=8E=B0openGauss=E5=85=BC=E5=AE=B9Oracle?= =?UTF-8?q?=E7=9A=84=E5=87=A0=E4=B8=AA=E6=9D=A1=E4=BB=B6=E8=A1=A8=E8=BE=BE?= =?UTF-8?q?=E5=BC=8F=E5=87=BD=E6=95=B0.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: wangshifei <18734596042@163.com> --- ...6\276\345\274\217\345\207\275\346\225\260" | 89 +++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 "app/zh/blogs/wangshifei/\346\204\217\345\244\226\345\217\221\347\216\260openGauss\345\205\274\345\256\271Oracle\347\232\204\345\207\240\344\270\252\346\235\241\344\273\266\350\241\250\350\276\276\345\274\217\345\207\275\346\225\260" diff --git "a/app/zh/blogs/wangshifei/\346\204\217\345\244\226\345\217\221\347\216\260openGauss\345\205\274\345\256\271Oracle\347\232\204\345\207\240\344\270\252\346\235\241\344\273\266\350\241\250\350\276\276\345\274\217\345\207\275\346\225\260" "b/app/zh/blogs/wangshifei/\346\204\217\345\244\226\345\217\221\347\216\260openGauss\345\205\274\345\256\271Oracle\347\232\204\345\207\240\344\270\252\346\235\241\344\273\266\350\241\250\350\276\276\345\274\217\345\207\275\346\225\260" new file mode 100644 index 00000000..b9e27023 --- /dev/null +++ "b/app/zh/blogs/wangshifei/\346\204\217\345\244\226\345\217\221\347\216\260openGauss\345\205\274\345\256\271Oracle\347\232\204\345\207\240\344\270\252\346\235\241\344\273\266\350\241\250\350\276\276\345\274\217\345\207\275\346\225\260" @@ -0,0 +1,89 @@ +--- +title: '【第七届openGauss技术文章征集】意外发现openGauss兼容Oracle的几个条件表达式函数' +date: '2024-10-15' +category: 'blog' +tags: ['openGauss'] +archives: '2024-04' +author: '墨竹' +summary: 'Just about everything you'll need to style in the theme:headings, paragraphs, blockquotes, tables, code blocks, and more.' +--- +# 意外发现openGauss兼容Oracle的几个条件表达式函数 + +最近工作中发现openGauss在兼容oracle模式下,可以兼容常用的两个条件表达式函数,因此就随手测试了一下。 + +## 查看数据库版本 + +``` +[omm@openGauss ~]$ gsql -r +gsql ((openGauss 6.0.0-RC1 build ed7f8e37) compiled at 2024-03-31 11:59:31 commit 0 last mr ) +Non-SSL connection (SSL connection is recommended when requiring high-security) +Type "help" for help. + +openGauss=# select version(); + version +----------------------------------------------------------------------------------------------------------------------------------------------------------- + (openGauss 6.0.0-RC1 build ed7f8e37) compiled at 2024-03-31 11:59:31 commit 0 last mr on x86_64-unknown-linux-gnu, compiled by g++ (GCC) 10.3.0, 64-bit +(1 row) + + +``` + +## 查看openGauss数据库的兼容模式 + +``` +testdb=# select datname,datcompatibility from pg_database; + datname | datcompatibility +-----------+------------------ + template1 | A + template0 | A + testdb | A + postgres | A +(4 rows) + +``` + +## decode(expr1, expr2, result1 ,…) + +将表达式base_expr与后面的每个compare(n) 进行比较,如果匹配返回相应的value(n)。如果没有发生匹配,则返回default。 +![decode.png](https://oss-emcsprod-public.modb.pro/image/editor/20240525-3073290c-a4e5-4265-a30a-8a727cfbaf40.png) +``` +testdb=# select id,name,address,decode(address,'北京市','BJ','南京市','NJ','ZG') JC from t1; + id | name | address | jc +----+------+---------+---- + 2 | zs2 | 北京市 | BJ + 4 | zs4 | | ZG + 1 | zs1 | 南京市 | NJ +(3 rows) + +``` + +## nvl(expr1, expr2) + +如果value1为NULL则返回value2,如果value1非NULL,则返回value1。 +![nvl.jpg](https://oss-emcsprod-public.modb.pro/image/editor/20240525-afaa9177-90a4-46db-9a37-9f10103a8173.jpg) +``` +testdb=# select * from t1; + id | name | address +----+------+--------- + 2 | zs2 | 北京市 + 4 | zs4 | +(2 rows) +testdb=# select id,name,nvl(address,'上海') from t1; + id | name | nvl +----+------+-------- + 2 | zs2 | 北京市 + 4 | zs4 | 上海 +(2 rows) +``` +decode和nvl的使用方法与在Oracle中的使用方式一致,并无差别,这里不做详细介绍。在查看文档过程,官网文档函数和操作符章节与whale插件支持的函数相关章节两个地方都描述了对nvl、decode的支持情况,但是也未发现两处的区别在哪儿?不清楚当使用插件和不使用的情况的功能区别在哪儿呢?另外也发现在oracle中开发经常使用的nvl2条件表达式也支持,但是使用需要使用whale插件后才可以使用;后来想安装whale插件测试,但是也没有对应版本插件下载的地方,只能下载源码自行编译,对于这块感觉还是有点不方便。由于时间的问题也没有进一步编译插件源码进行测试。 + + + + + + + + + + + -- Gitee From ba09fa326fa022de940fd0995c96032a034b5906 Mon Sep 17 00:00:00 2001 From: wangshifei <18734596042@163.com> Date: Fri, 18 Oct 2024 08:37:06 +0000 Subject: [PATCH 05/13] =?UTF-8?q?add=20app/zh/blogs/wangshifei/openGauss?= =?UTF-8?q?=E4=B8=80=E7=A7=8D=E7=B4=A2=E5=BC=95=E5=AE=9E=E7=8E=B0=E4=B8=89?= =?UTF-8?q?=E7=A7=8D=E6=89=AB=E6=8F=8F=E6=96=B9=E5=BC=8F=EF=BC=9A=E4=BD=8D?= =?UTF-8?q?=E5=9B=BE=E3=80=81=E7=B4=A2=E5=BC=95=E5=92=8C=E4=BB=85=E7=B4=A2?= =?UTF-8?q?=E5=BC=95.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: wangshifei <18734596042@163.com> --- ...2\214\344\273\205\347\264\242\345\274\225" | 289 ++++++++++++++++++ 1 file changed, 289 insertions(+) create mode 100644 "app/zh/blogs/wangshifei/openGauss\344\270\200\347\247\215\347\264\242\345\274\225\345\256\236\347\216\260\344\270\211\347\247\215\346\211\253\346\217\217\346\226\271\345\274\217\357\274\232\344\275\215\345\233\276\343\200\201\347\264\242\345\274\225\345\222\214\344\273\205\347\264\242\345\274\225" diff --git "a/app/zh/blogs/wangshifei/openGauss\344\270\200\347\247\215\347\264\242\345\274\225\345\256\236\347\216\260\344\270\211\347\247\215\346\211\253\346\217\217\346\226\271\345\274\217\357\274\232\344\275\215\345\233\276\343\200\201\347\264\242\345\274\225\345\222\214\344\273\205\347\264\242\345\274\225" "b/app/zh/blogs/wangshifei/openGauss\344\270\200\347\247\215\347\264\242\345\274\225\345\256\236\347\216\260\344\270\211\347\247\215\346\211\253\346\217\217\346\226\271\345\274\217\357\274\232\344\275\215\345\233\276\343\200\201\347\264\242\345\274\225\345\222\214\344\273\205\347\264\242\345\274\225" new file mode 100644 index 00000000..c5cc9124 --- /dev/null +++ "b/app/zh/blogs/wangshifei/openGauss\344\270\200\347\247\215\347\264\242\345\274\225\345\256\236\347\216\260\344\270\211\347\247\215\346\211\253\346\217\217\346\226\271\345\274\217\357\274\232\344\275\215\345\233\276\343\200\201\347\264\242\345\274\225\345\222\214\344\273\205\347\264\242\345\274\225" @@ -0,0 +1,289 @@ +# openGauss一种索引实现三种扫描方式:位图、索引和仅索引 + +性能问题应该是我们日常运维过程中遇到最多的一类的问题,也是用户吐槽最多的问题之一,而解决性能问题最常见的方法就是为表创建合适的索引。索引可以节省大量数据访问时间以及引导查询以最快的方式获取结果,从而大幅度提升sql语句的查询性能。 + +在openGauss或者PG系列的数据库中,有不同的扫描方式可以利用索引来生成高效的执行计划。在这边文章中,我们将对openGauss的三种不同的索引扫描方式进行详细讲解,主要依据查询的表、查询检索的内容、使用的过滤器。三种不同的索引扫描类型: + +- 索引扫描 +- 仅索引扫描 +- 位图索引扫描 + +## 准备测试用例 + +在这里我们将使用只有一个单索引的表来演示,这样可以减少一些其他因素的影响,也会直观的感受到扫描方式又是受到什么样的过滤条件而改变。 + +先创建一个person的业务表 + +``` +create table person( + id serial primary key, + name text not null, + age integer not null, + email text not null, + register_date timestamp default now() not null, + is_active boolean DEFAULT true NOT NULL +); +``` + +然后使用SQL语句向表中插入100w行数据。 + +``` +INSERT INTO person(name,age,email,register_date,is_active) + SELECT md5(random()::text), + floor(random() * 99)::int, + md5(random()::text) || '@163.com', + now() - (random() * (interval '90 days')), + case when random() > 0.5 then true else false end +  FROM generate_series(1, 1000000); +``` + +## 创建索引 + +为了满足测试用例的要求,在这里我们需要添加一个复合索引,可以让我们看到不同的索引扫描方式。 + +``` +create index idx_person_age_date_active on person(age,register_date,is_active); +``` + +下面我们再来看一下,创建索引的三列的基数,即该列唯一键的数量。 + +age字段:我们使用random函数并通过floor函数限制了结果,使得结果的取值范围为[1,99] + +register_date字段:该字段的取值每行都不同,是这三个字段中值重复度最低的。 + +is_active字段:该列是布尔值,因此只能有true和false 两个不同的值 + +我们也可以通过查看数据库的pg_stats视图来验证索引列的基数。为了确保统计信息的准确性,我们需要对该表重新收集统计信息。 + +``` +ANALYZE person; +``` + +查看pg_stats视图 + +``` +SELECT tablename,attname AS column_name,n_distinct AS dist_val + FROM pg_stats + WHERE tablename = 'person' + AND attname IN ('age','register_date','is_active') + ORDER BY dist_val DESC; + tablename | column_name | dist_val +-----------+---------------+---------- + person | age | 99 + person | is_active | 2 + person | register_date | -1 +(3 rows) +``` + +针对n_distinct的字段,age列有99个不同的值,is_active有2个值,register_date列显示负值-1。 + +在通过查看openGauss的官网文档中对于pg_stats视图n_distinct列的解释: + +> -1表示一个唯一字段,独立数值的个数和行数相同 + +其实就可以理解为不同值的数量可能与总数量相同。 + +## 无索引-顺序扫描 + +我们先来看一下不带过滤条件的查询语句的执行计划 + +``` +test=# EXPLAIN ANALYZE SELECT * FROM person; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------ + Seq Scan on person (cost=0.00..26394.00 rows=1000000 width=81) (actual time=0.010..86.210 rows=1000000 loops=1) + Total runtime: 123.725 ms +(2 rows) + +``` + +可以看到,由于需要从表中检索所有的数据,优化器决定使用顺序扫描方式,扫描了100W行,总耗时为123.725 ms + +## 位图索引扫描 + +### 使用索引 + +当查询需要访问大量的数据(可以利用批量读取(如顺序扫描)的优势)但又没有大到需要处理所有表数据时,优化器会选择位图索引扫描方式。位图索引扫描可以理解介于顺序扫描和索引扫描之间的方式,是一种折中处理的方式。 当我们看到执行计划使用了位图索引时,你会发现Bitmap Index Scan和Bitmap Heap Scan一般都是成对出现并配合使用,其中Bitmap Index Scan先在索引中查找符合条件的行并在内存中创建位图,而Bitmap Heap Scan使用该位图到表的数据文件中读取数据文件中的数据。 + +下面,我们来看看位图索引扫描的执行计划 + +``` +test=# EXPLAIN ANALYZE SELECT * FROM person where age =30; + QUERY PLAN + +------------------------------------------------------------------------------------------------------------------------ +--------------------- + Bitmap Heap Scan on person (cost=139.00..10860.76 rows=5000 width=81) (actual time=2.357..11.236 rows=10052 loops=1) + Recheck Cond: (age = 30) + Heap Blocks: exact=7502 + -> Bitmap Index Scan on idx_person_age_date_active (cost=0.00..137.75 rows=5000 width=0) (actual time=1.412..1.412 + rows=10052 loops=1) + Index Cond: (age = 30) + Total runtime: 11.839 ms +(6 rows) +``` + +在上述的执行计划中可知,首先使用了idx_person_age_date_active索引的位图索引扫描,把满足条件的行在内存中创建一个位图,并将其传递到父节点,即person表上的Bitmap Heap Scan路径,然后使用该位图到表中扫描,最后从表中读取完数据后仍需要重新检查一下过滤条件,并返回数据结果集。 + +### 未使用索引 + +我们再来看一下未使用索引时,执行计划是什么样的。需要禁用位图扫描参数. + +``` +set enable_bitmapscan =off; +``` + +下面,再次执行SQL语句 + +``` +test=# EXPLAIN ANALYZE SELECT * FROM person where age =30; + QUERY PLAN +-------------------------------------------------------------------------------------------------------------- + Seq Scan on person (cost=0.00..28894.00 rows=9600 width=91) (actual time=0.086..140.609 rows=10052 loops=1) + Filter: (age = 30) + Rows Removed by Filter: 989948 + Total runtime: 141.180 ms +(4 rows) + +``` + +从执行的结果中可知,使用位图索引扫描比顺序扫描,执行耗时上快了10倍多,cost降低1倍。也就是位图索引扫描利用批量读取有限数量的页面比直接顺序扫描执行速度更快,执行计划更优。 + +``` +--重置位图索引扫描参数 +reset enable_bitmapscan; +``` + +## 索引扫描 + +索引扫描的过程可以分成两步,第一步是从索引中获取行的物理位置,第二步是再到表的数据文件中读取相应的数据的过程,即从从堆或表页中读取数据。因此每次索引扫描访问都是两次读操作,但是该操作仍然是从表中检索数据的最有效的方式之一。当查询的行数较小时,优化器会选择这种扫描方式,因为索引扫描方式比顺序扫描读取数据有更低的cost且速度更快。 + +以下是索引扫描的执行计划 + +``` +test=# EXPLAIN ANALYZE SELECT * FROM person where age =8 and register_date ='2024-10-10 13:30:07.262557'::timestamp; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------- + [Bypass] + Index Scan using idx_person_age_date_active on person (cost=0.00..8.27 rows=1 width=91) (actual time=0.014..0.015 rows=1 loops=1) + Index Cond: ((age = 8) AND (register_date = '2024-10-10 13:30:07.262557'::timestamp without time zone)) + Total runtime: 0.160 ms +(4 rows) + +``` + +在上面的执行计划可知,本次使用的sql是在之前的sql的基础上,添加了一个过滤条件age =8 and register_date ='2024-10-10 13:30:07.262557'::timestamp。由于register_date是多列索引idx_person_age_date_active的一部分,且register_date重复度很高,因此基本就是从索引中一次读取就可以获取行位置,然后从该物理位置的表页中获取行数据,查询耗时0.160ms,速度是相当哇塞。 + +在上面的测试用例中,SQL语句中的register_date列使用了固定的时间戳值进行过滤,但是如果我们对register_date列使用范围过滤,结果集行数较少,优化器仍然会选择对多行进行索引扫描,就比如下面的测试用例。 + +``` +test=# EXPLAIN ANALYZE SELECT * FROM person where age =8 and register_date >'2024-10-10 10:00:00'::timestamp and register_date <'2024-10-10 11:00:00'::timestamp; + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + [Bypass] + Index Scan using idx_person_age_date_active on person (cost=0.00..24.36 rows=5 width=91) (actual time=0.015..0.023 rows=5 loops=1) + Index Cond: ((age = 8) AND (register_date > '2024-10-10 10:00:00'::timestamp without time zone) AND (register_date < '2024-10-10 11:00:00'::timestamp without time zone)) + Total runtime: 0.087 ms +(4 rows) + +Time: 0.901 ms + +``` + +从上面的执行计划看出,优化器估算的rows为5行,实际扫描的行数也是5行,尽管读取的数据行数增加,但是执行仍然很快,用时0.901ms。 + +## 仅索引扫描 + +### 仅索引扫描 + +仅索引扫描方式是对索引扫描方式的改进的一种方法。当SQl查询的数据都已经存在于索引中时,openGauss会使用该方法,通俗的讲就是SELECT和WHERE子句中的列或表达式应该是索引的一部分,因此索引扫描的第二步在这里就不需要了,仅从索引中读取数据返回结果。 + +下面,通过测试用例来说明一下 + +``` +test=# EXPLAIN ANALYZE SELECT age,register_date,is_active FROM person where age =8 and register_date ='2024-10-10 13:30:07.262557'::timestamp; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------ + [Bypass] + Index Only Scan using idx_person_age_date_active on person (cost=0.00..8.27 rows=1 width=13) (actual time=0.055..0.056 rows=1 loops=1) + Index Cond: ((age = 8) AND (register_date = '2024-10-10 13:30:07.262557'::timestamp without time zone)) + Heap Fetches: 1 + Total runtime: 0.115 ms +(5 rows) +``` + +从上面的执行计划可以看出,EXPLAIN输出显示Index Only Scan,但是Heap Fetches的值为1,也就是准确扫描到数据块的个数是1。 + +>Heap Fetches表明需要扫描数据块的个数,虽然Index Only Scan 可以从索引直接输出结果,但是因为MVCC 机制的实现,需要对扫描的元组进行可见性判断,即检查visibility MAP 文件。当新建表之后,如果没有进行过vacuum和autovacuum操作,这时还没有VM文件,而索引并没有保存记录的版本信息,索引Index Only Scan 还是需要扫描数据块(Heap Fetches 代表需要扫描的数据块个数)来获取版本信息,这个时候可能会比Index Scan 慢。 + +执行一下vacuum操作 + +``` +vacuum; +``` + +再次执行查询语句 + +``` +test=# EXPLAIN ANALYZE SELECT age,register_date,is_active FROM person where age =8 and register_date ='2024-10-10 13:30:07.262557'::timestamp; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------ + [Bypass] + Index Only Scan using idx_person_age_date_active on person (cost=0.00..4.27 rows=1 width=13) (actual time=0.013..0.014 rows=1 loops=1) + Index Cond: ((age = 8) AND (register_date = '2024-10-10 13:30:07.262557'::timestamp without time zone)) + Heap Fetches: 0 + Total runtime: 0.051 ms +(5 rows) +``` + +这一次,在执行计划中不止看到了Index Only Scan,而且Heap Fetches的值为0,也就是没有从表页中访问过数据块。时间相对比Index Scan还要好,只有0.051ms + +>执行计划中 Heap Fetches: 0 表示没有回表取数据, 存在2种情况: +>1)通过索引判断真的没有数据,所以不需要回表 +>2)通过索引判断真的有数据,再一次根据VM 判断,全部元祖是新的,所以从索引中就能获得最新的数据, 所以不需要回表 + +### 不合理的索引 + +如果对所有列建立索引,从而使的索引包含与表相同的所有数据,这应该是一种错误的认知也不是一个好的想法。如果是这种情况,将看不到使用索引的任何优势,优化器也将会选择顺序扫描方式。 + +下面,我们将在所有的列上建索引,然后观察sql的执行计划 + +``` +DROP INDEX idx_person_age_date_active; +CREATE INDEX idx_person_all ON person(id,name,age,email,register_date,is_active); +ANALYZE person; + +test=# EXPLAIN ANALYZE SELECT * FROM person where age =8 and register_date ='2024-10-10 13:30:07.262557'::timestamp; + QUERY PLAN +------------------------------------------------------------------------------------------------------- + Seq Scan on person (cost=0.00..31394.00 rows=1 width=91) (actual time=0.359..118.933 rows=1 loops=1) + Filter: ((age = 8) AND (register_date = '2024-10-10 13:30:07.262557'::timestamp without time zone)) + Rows Removed by Filter: 999999 + Total runtime: 119.077 ms +(4 rows) + +``` + +在上面的测试用例中,删除了之前新建的多列索引,并对所有列创建了一个新索引,然后执行ANALYZE刷新统计信息并执行查询语句。 + +在这里我们查询了所有的列,但是优化器选择了顺序扫描的方式,执行耗时为119.077ms。 + +## 总结 + +openGauss的优化器可以根据存储的数据和在查询过滤条件上使用单个索引的不同,可以产生不同的扫描方式。最后,我们大概最做一下总结。 + +1、在基数大的列上创建索引,在对该列进行查询过滤的时可以获得最佳的性能,但是如果在基数较低的列上创建索引会产生相反的效果,因为优化器大部分情况用不到该索引,而且还需要对该索引额为的维护。 + +2、当查询小结果集或精确查询时,索引扫描应该是最优的方法,可以快速的检索数据。 + +3、当查询需要访问大量的数据(可以利用批量读取(如顺序扫描)的优势)但又没有大到需要处理所有表数据时,优化器会选择位图索引扫描方式。 + +4、如果查询所需要的列且列很少,可以利用仅索引扫描方式可以避免从堆或表页中进行读取数据。另外,除了多列索引可以使得优化器选择Index Only Scan,还可以考虑使用索引覆盖,INCLUDE 子句指定将一些非键列(non-key columns)包含在索引中, 可以直接返回非键列中的内容,而不必去访问索引所对应的堆表。 + +## 参考 + +PostgreSQL修炼之道从小工到专家(第二版) + +https://www.modb.pro/db/449252 + +https://www.modb.pro/issue/18165 \ No newline at end of file -- Gitee From 2eefaeec3e5f845cdf5a5bda50aa08e68c93d8e1 Mon Sep 17 00:00:00 2001 From: wangshifei <18734596042@163.com> Date: Mon, 21 Oct 2024 00:50:49 +0000 Subject: [PATCH 06/13] =?UTF-8?q?update=20app/zh/blogs/wangshifei/openGaus?= =?UTF-8?q?s=E4=B8=80=E7=A7=8D=E7=B4=A2=E5=BC=95=E5=AE=9E=E7=8E=B0?= =?UTF-8?q?=E4=B8=89=E7=A7=8D=E6=89=AB=E6=8F=8F=E6=96=B9=E5=BC=8F=EF=BC=9A?= =?UTF-8?q?=E4=BD=8D=E5=9B=BE=E3=80=81=E7=B4=A2=E5=BC=95=E5=92=8C=E4=BB=85?= =?UTF-8?q?=E7=B4=A2=E5=BC=95.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: wangshifei <18734596042@163.com> --- ...\225\345\222\214\344\273\205\347\264\242\345\274\225" | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git "a/app/zh/blogs/wangshifei/openGauss\344\270\200\347\247\215\347\264\242\345\274\225\345\256\236\347\216\260\344\270\211\347\247\215\346\211\253\346\217\217\346\226\271\345\274\217\357\274\232\344\275\215\345\233\276\343\200\201\347\264\242\345\274\225\345\222\214\344\273\205\347\264\242\345\274\225" "b/app/zh/blogs/wangshifei/openGauss\344\270\200\347\247\215\347\264\242\345\274\225\345\256\236\347\216\260\344\270\211\347\247\215\346\211\253\346\217\217\346\226\271\345\274\217\357\274\232\344\275\215\345\233\276\343\200\201\347\264\242\345\274\225\345\222\214\344\273\205\347\264\242\345\274\225" index c5cc9124..44682e2a 100644 --- "a/app/zh/blogs/wangshifei/openGauss\344\270\200\347\247\215\347\264\242\345\274\225\345\256\236\347\216\260\344\270\211\347\247\215\346\211\253\346\217\217\346\226\271\345\274\217\357\274\232\344\275\215\345\233\276\343\200\201\347\264\242\345\274\225\345\222\214\344\273\205\347\264\242\345\274\225" +++ "b/app/zh/blogs/wangshifei/openGauss\344\270\200\347\247\215\347\264\242\345\274\225\345\256\236\347\216\260\344\270\211\347\247\215\346\211\253\346\217\217\346\226\271\345\274\217\357\274\232\344\275\215\345\233\276\343\200\201\347\264\242\345\274\225\345\222\214\344\273\205\347\264\242\345\274\225" @@ -1,3 +1,12 @@ +--- +title: '【第八届openGauss技术文章征集】openGauss一种索引实现三种扫描方式:位图、索引和仅索引' +date: '2024-10-18' +category: 'blog' +tags: ['openGauss'] +archives: '2024-10' +author: '墨竹' +summary: 'Just about everything you'll need to style in the theme:headings, paragraphs, blockquotes, tables, code blocks, and more.' +--- # openGauss一种索引实现三种扫描方式:位图、索引和仅索引 性能问题应该是我们日常运维过程中遇到最多的一类的问题,也是用户吐槽最多的问题之一,而解决性能问题最常见的方法就是为表创建合适的索引。索引可以节省大量数据访问时间以及引导查询以最快的方式获取结果,从而大幅度提升sql语句的查询性能。 -- Gitee From d3a5264df5fa200f23cec2bb0856dcdc111f53c3 Mon Sep 17 00:00:00 2001 From: wangshifei <18734596042@163.com> Date: Tue, 5 Nov 2024 00:52:15 +0000 Subject: [PATCH 07/13] =?UTF-8?q?=E5=B8=A6=E4=BD=A0=E4=BD=93=E9=AA=8C?= =?UTF-8?q?=E4=B8=80=E4=B8=8BopenGauss6.0=E5=85=A8=E9=93=BE=E8=B7=AF?= =?UTF-8?q?=E8=B7=9F=E8=B8=AA=E8=83=BD=E5=8A=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: wangshifei <18734596042@163.com> --- .../image-20241104164958909.png | Bin 0 -> 14267 bytes .../image-20241104170751474.png | Bin 0 -> 41313 bytes .../image-20241104170854961.png | Bin 0 -> 33706 bytes app/zh/blogs/wangshifei/20241102.md | 130 ++++++++++++++++++ 4 files changed, 130 insertions(+) create mode 100644 app/zh/blogs/wangshifei/20241102.assets/image-20241104164958909.png create mode 100644 app/zh/blogs/wangshifei/20241102.assets/image-20241104170751474.png create mode 100644 app/zh/blogs/wangshifei/20241102.assets/image-20241104170854961.png create mode 100644 app/zh/blogs/wangshifei/20241102.md diff --git a/app/zh/blogs/wangshifei/20241102.assets/image-20241104164958909.png b/app/zh/blogs/wangshifei/20241102.assets/image-20241104164958909.png new file mode 100644 index 0000000000000000000000000000000000000000..d41b8fb02d37474ea1f889b95e0daaeff919d997 GIT binary patch literal 14267 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 z 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 UjBDDzK|p(~^i;82!Tk0A0W3e4B>(^b literal 0 HcmV?d00001 diff --git a/app/zh/blogs/wangshifei/20241102.md b/app/zh/blogs/wangshifei/20241102.md new file mode 100644 index 00000000..49b3e657 --- /dev/null +++ b/app/zh/blogs/wangshifei/20241102.md @@ -0,0 +1,130 @@ +# 带你体验一下openGauss6.0全链路跟踪能力 + +在openGauss6.0版本中的可维护性中介绍全链路跟踪能力,主要是追踪并记录sql语句从客户端到数据库服务端网络耗时。这个功能主要是为了解决无法监控网络耗时,因为有些时候,当我们执行一个问题sql执行,有时会发现在服务器端执行没有问题,但是在客户端执行比较慢的问题。现在有全链路跟踪能力,就可以快速的知道一个sql的网络耗时,可以快速的定位sql性能是否与网络相关。 + +## 版本特性描述 + +可维护性:支持全链路跟踪能力 + +- 实现追踪并记录jdbc查询接口执行sql的端到端网络耗时,并记录在数据库dbe_perf.statement视图、statement_history表中。 + +## 支持条件 + +仅当**openGauss server版本和jdbc版本均大于6.0**时,才支持全链路跟踪能力。目前仅有jdbc版本的驱动。另外虽然该特性涉及与jdbc与数据库的交互能力,但是用户只需要在数据库内核设置enable_record_nettime参数是否开启该功能。 + +## enable_record_nettime说明 + +``` +参数说明:控制驱动全链路跟踪功能的开关,on为开,off为关。参数打开后将驱动执行的sql网络链路耗时记录在statement_history表中,通过dbe_perf.statement视图,standby_statement_history函数可以查询链路网络耗时net_trans_time,且wdr报告中TimeModel支持查看net_trans_time。当前仅支持6.0.0以上版本的JDBC驱动。 +该参数属于USERSET类型参数,请参考表1中对应设置方法进行设置。 +取值范围:布尔型 +默认值:off +``` + +## 网络链路耗时查询方式 + +可以查看dbe_perf.statement视图、statement_history表的net_trans_time字段来查看网络链路的耗时,单位是微妙。 + +``` +select query,net_trans_time,last_updated from dbe_perf.statement; +select query,start_time,finish_time,net_trans_time from statement_history; +``` + +## 准备测试用例表 + +在这里我们准备一个简单的测试用例表,来验证简单的增删改查。 + +``` +create table t1(id int primary key,name varchar(100),address varchar(100)); +insert into t1 values(1,'wang1','beijing'); +insert into t1 values(2,'wang2','beijing'); +insert into t1 values(3,'wang3','beijing'); +insert into t1 values(4,'wang4','beijing'); +``` + +## 查看enable_record_nettime默认的值 + +``` +openGauss=# show enable_record_nettime; + enable_record_nettime +----------------------- + off +(1 row) +``` + +## 开启全链路跟踪开关 + +可以使用guc命令来修改enable_record_nettime值为on,开启全链路跟踪功能。另外还需要修改log_min_duration_statement和track_stmt_stat_level参数。 + +**log_min_duration_statement**表示慢SQL阈值,如果为0则全量收集,时间单位为毫秒; + +**track_stmt_stat_level**表示信息捕获的级别,建议设置为track_stmt_stat_level='L0,L0' + +``` +gs_guc reload -N all -I all -c 'enable_record_nettime=on'; +gs_guc reload -N all -I all -c 'log_min_duration_statement=0'; +gs_guc reload -N all -I all -c "track_stmt_stat_level='L0,L0'"; +``` + +## 在客户端执行测试SQL语句 + +``` +select address,max(id) from t1 group by address; +``` + +![image-20241104164958909](20241102.assets/image-20241104164958909.png) + +## 查看dbe_perf.statement视图中的信息 + +``` +openGauss=# select query,net_trans_time,last_updated from dbe_perf.statement where user_name ='test' and query like '%t1%' order by last_updated desc; + query | net_trans_time | last_updated +----------------------------------------------------------------------------+----------------+------------------------------- + select address,max(id) from t1 group by address | 1294 | 2024-11-04 16:50:03.036603+08 + select * from t1 | 1793 | 2024-11-04 16:49:00.123864+08 + select max(name) from t1 | 978 | 2024-11-04 16:37:33.611782+08 + select max(?) from t1 | 2564 | 2024-11-04 16:32:55.269171+08 + vacuum t1; | 0 | 2024-11-04 16:32:19.137282+08 + select count(?) from t1 | 9708 | 2024-11-04 16:11:06.538974+08 + insert into t1 values(?,?,?) | 0 | 2024-11-04 14:53:35.988101+08 + create table t1(id int primary key,name varchar(100),address varchar(100)) | 0 | 2024-11-04 14:53:29.41779+08 +(8 rows) +``` + + + +![image-20241104170854961](20241102.assets/image-20241104170854961.png) + +通过测试结果,可以看出在dbe_perf.statement已经记录刚才执行的sql,并且网络消耗的时间为1294us。 + +## 查看statement_history表中的记录信息 + +``` +openGauss=# select query,start_time,finish_time,net_trans_time from statement_history t where user_name ='test' and query like '%t1%' order by start_time desc limit 10; + query | start_time | finish_time | net_trans_time +-------------------------------------------------+-------------------------------+-------------------------------+---------------- + select address,max(id) from t1 group by address | 2024-11-04 16:49:40.847096+08 | 2024-11-04 16:49:40.848015+08 | 1294 + select address,max(id) from t1 group by address | 2024-11-04 16:49:40.846453+08 | 2024-11-04 16:49:40.847074+08 | 0 + select * from t1 | 2024-11-04 16:48:55.543124+08 | 2024-11-04 16:48:55.543701+08 | 899 + select * from t1 | 2024-11-04 16:48:55.54295+08 | 2024-11-04 16:48:55.543113+08 | 0 + select * from t1 | 2024-11-04 16:37:33.611937+08 | 2024-11-04 16:37:33.61237+08 | 894 + select * from t1 | 2024-11-04 16:37:33.611803+08 | 2024-11-04 16:37:33.611931+08 | 0 + select max(name) from t1 | 2024-11-04 16:33:25.862634+08 | 2024-11-04 16:33:25.863255+08 | 978 + select max(name) from t1 | 2024-11-04 16:33:25.862076+08 | 2024-11-04 16:33:25.862622+08 | 0 + vacuum t1; | 2024-11-04 16:32:19.123703+08 | 2024-11-04 16:32:19.137293+08 | 0 + select max(?) from t1 | 2024-11-04 16:27:26.614458+08 | 2024-11-04 16:27:26.615534+08 | 2564 +(10 rows) + +``` + +![image-20241104170751474](20241102.assets/image-20241104170751474.png) + +通过上面的查询可知,在statement_history也已经有执行sql的记录,网络消耗的时间为1294us和dbe_perf.statement的值一致。 + +## 总结 + +全链路跟踪能力是对数据库问题定位工具的完善,对于数据库运维的老师来说又是一个好的消息。 在这边文章中我只是带领大家初步了解一下全链路跟踪能力怎么查看,但是详细的内部原理,大家可以参考openGauss官网视频号中对于该功能的详细介绍。 + +## 参考 + +【openGauss 6.0.0 LTS版本特性解读(四) | openGauss 全链路跟踪】https://www.bilibili.com/video/BV1gFSRYKErB?vd_source=0741f9621c39156deebce32bbdc2a50c \ No newline at end of file -- Gitee From bf448d7f16a00845e9c7c3bedd2ecc5df6135974 Mon Sep 17 00:00:00 2001 From: wangshifei <18734596042@163.com> Date: Tue, 5 Nov 2024 00:53:00 +0000 Subject: [PATCH 08/13] =?UTF-8?q?=E9=87=8D=E5=91=BD=E5=90=8D=20app/zh/blog?= =?UTF-8?q?s/wangshifei/20241102.md=20=E4=B8=BA=20app/zh/blogs/wangshifei/?= =?UTF-8?q?=E5=B8=A6=E4=BD=A0=E4=BD=93=E9=AA=8C=E4=B8=80=E4=B8=8BopenGauss?= =?UTF-8?q?6.0=E5=85=A8=E9=93=BE=E8=B7=AF=E8=B7=9F=E8=B8=AA=E8=83=BD?= =?UTF-8?q?=E5=8A=9B.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...50\267\257\350\267\237\350\270\252\350\203\275\345\212\233.md" | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename app/zh/blogs/wangshifei/20241102.md => "app/zh/blogs/wangshifei/\345\270\246\344\275\240\344\275\223\351\252\214\344\270\200\344\270\213openGauss6.0\345\205\250\351\223\276\350\267\257\350\267\237\350\270\252\350\203\275\345\212\233.md" (100%) diff --git a/app/zh/blogs/wangshifei/20241102.md "b/app/zh/blogs/wangshifei/\345\270\246\344\275\240\344\275\223\351\252\214\344\270\200\344\270\213openGauss6.0\345\205\250\351\223\276\350\267\257\350\267\237\350\270\252\350\203\275\345\212\233.md" similarity index 100% rename from app/zh/blogs/wangshifei/20241102.md rename to "app/zh/blogs/wangshifei/\345\270\246\344\275\240\344\275\223\351\252\214\344\270\200\344\270\213openGauss6.0\345\205\250\351\223\276\350\267\257\350\267\237\350\270\252\350\203\275\345\212\233.md" -- Gitee From d0881bec1dfd787eaec523ba5247eedf28f620d3 Mon Sep 17 00:00:00 2001 From: wangshifei <18734596042@163.com> Date: Tue, 5 Nov 2024 00:53:40 +0000 Subject: [PATCH 09/13] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20ap?= =?UTF-8?q?p/zh/blogs/wangshifei/=E5=B8=A6=E4=BD=A0=E4=BD=93=E9=AA=8C?= =?UTF-8?q?=E4=B8=80=E4=B8=8BopenGauss6.0=E5=85=A8=E9=93=BE=E8=B7=AF?= =?UTF-8?q?=E8=B7=9F=E8=B8=AA=E8=83=BD=E5=8A=9B.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...37\350\270\252\350\203\275\345\212\233.md" | 130 ------------------ 1 file changed, 130 deletions(-) delete mode 100644 "app/zh/blogs/wangshifei/\345\270\246\344\275\240\344\275\223\351\252\214\344\270\200\344\270\213openGauss6.0\345\205\250\351\223\276\350\267\257\350\267\237\350\270\252\350\203\275\345\212\233.md" diff --git "a/app/zh/blogs/wangshifei/\345\270\246\344\275\240\344\275\223\351\252\214\344\270\200\344\270\213openGauss6.0\345\205\250\351\223\276\350\267\257\350\267\237\350\270\252\350\203\275\345\212\233.md" "b/app/zh/blogs/wangshifei/\345\270\246\344\275\240\344\275\223\351\252\214\344\270\200\344\270\213openGauss6.0\345\205\250\351\223\276\350\267\257\350\267\237\350\270\252\350\203\275\345\212\233.md" deleted file mode 100644 index 49b3e657..00000000 --- "a/app/zh/blogs/wangshifei/\345\270\246\344\275\240\344\275\223\351\252\214\344\270\200\344\270\213openGauss6.0\345\205\250\351\223\276\350\267\257\350\267\237\350\270\252\350\203\275\345\212\233.md" +++ /dev/null @@ -1,130 +0,0 @@ -# 带你体验一下openGauss6.0全链路跟踪能力 - -在openGauss6.0版本中的可维护性中介绍全链路跟踪能力,主要是追踪并记录sql语句从客户端到数据库服务端网络耗时。这个功能主要是为了解决无法监控网络耗时,因为有些时候,当我们执行一个问题sql执行,有时会发现在服务器端执行没有问题,但是在客户端执行比较慢的问题。现在有全链路跟踪能力,就可以快速的知道一个sql的网络耗时,可以快速的定位sql性能是否与网络相关。 - -## 版本特性描述 - -可维护性:支持全链路跟踪能力 - -- 实现追踪并记录jdbc查询接口执行sql的端到端网络耗时,并记录在数据库dbe_perf.statement视图、statement_history表中。 - -## 支持条件 - -仅当**openGauss server版本和jdbc版本均大于6.0**时,才支持全链路跟踪能力。目前仅有jdbc版本的驱动。另外虽然该特性涉及与jdbc与数据库的交互能力,但是用户只需要在数据库内核设置enable_record_nettime参数是否开启该功能。 - -## enable_record_nettime说明 - -``` -参数说明:控制驱动全链路跟踪功能的开关,on为开,off为关。参数打开后将驱动执行的sql网络链路耗时记录在statement_history表中,通过dbe_perf.statement视图,standby_statement_history函数可以查询链路网络耗时net_trans_time,且wdr报告中TimeModel支持查看net_trans_time。当前仅支持6.0.0以上版本的JDBC驱动。 -该参数属于USERSET类型参数,请参考表1中对应设置方法进行设置。 -取值范围:布尔型 -默认值:off -``` - -## 网络链路耗时查询方式 - -可以查看dbe_perf.statement视图、statement_history表的net_trans_time字段来查看网络链路的耗时,单位是微妙。 - -``` -select query,net_trans_time,last_updated from dbe_perf.statement; -select query,start_time,finish_time,net_trans_time from statement_history; -``` - -## 准备测试用例表 - -在这里我们准备一个简单的测试用例表,来验证简单的增删改查。 - -``` -create table t1(id int primary key,name varchar(100),address varchar(100)); -insert into t1 values(1,'wang1','beijing'); -insert into t1 values(2,'wang2','beijing'); -insert into t1 values(3,'wang3','beijing'); -insert into t1 values(4,'wang4','beijing'); -``` - -## 查看enable_record_nettime默认的值 - -``` -openGauss=# show enable_record_nettime; - enable_record_nettime ------------------------ - off -(1 row) -``` - -## 开启全链路跟踪开关 - -可以使用guc命令来修改enable_record_nettime值为on,开启全链路跟踪功能。另外还需要修改log_min_duration_statement和track_stmt_stat_level参数。 - -**log_min_duration_statement**表示慢SQL阈值,如果为0则全量收集,时间单位为毫秒; - -**track_stmt_stat_level**表示信息捕获的级别,建议设置为track_stmt_stat_level='L0,L0' - -``` -gs_guc reload -N all -I all -c 'enable_record_nettime=on'; -gs_guc reload -N all -I all -c 'log_min_duration_statement=0'; -gs_guc reload -N all -I all -c "track_stmt_stat_level='L0,L0'"; -``` - -## 在客户端执行测试SQL语句 - -``` -select address,max(id) from t1 group by address; -``` - -![image-20241104164958909](20241102.assets/image-20241104164958909.png) - -## 查看dbe_perf.statement视图中的信息 - -``` -openGauss=# select query,net_trans_time,last_updated from dbe_perf.statement where user_name ='test' and query like '%t1%' order by last_updated desc; - query | net_trans_time | last_updated -----------------------------------------------------------------------------+----------------+------------------------------- - select address,max(id) from t1 group by address | 1294 | 2024-11-04 16:50:03.036603+08 - select * from t1 | 1793 | 2024-11-04 16:49:00.123864+08 - select max(name) from t1 | 978 | 2024-11-04 16:37:33.611782+08 - select max(?) from t1 | 2564 | 2024-11-04 16:32:55.269171+08 - vacuum t1; | 0 | 2024-11-04 16:32:19.137282+08 - select count(?) from t1 | 9708 | 2024-11-04 16:11:06.538974+08 - insert into t1 values(?,?,?) | 0 | 2024-11-04 14:53:35.988101+08 - create table t1(id int primary key,name varchar(100),address varchar(100)) | 0 | 2024-11-04 14:53:29.41779+08 -(8 rows) -``` - - - -![image-20241104170854961](20241102.assets/image-20241104170854961.png) - -通过测试结果,可以看出在dbe_perf.statement已经记录刚才执行的sql,并且网络消耗的时间为1294us。 - -## 查看statement_history表中的记录信息 - -``` -openGauss=# select query,start_time,finish_time,net_trans_time from statement_history t where user_name ='test' and query like '%t1%' order by start_time desc limit 10; - query | start_time | finish_time | net_trans_time --------------------------------------------------+-------------------------------+-------------------------------+---------------- - select address,max(id) from t1 group by address | 2024-11-04 16:49:40.847096+08 | 2024-11-04 16:49:40.848015+08 | 1294 - select address,max(id) from t1 group by address | 2024-11-04 16:49:40.846453+08 | 2024-11-04 16:49:40.847074+08 | 0 - select * from t1 | 2024-11-04 16:48:55.543124+08 | 2024-11-04 16:48:55.543701+08 | 899 - select * from t1 | 2024-11-04 16:48:55.54295+08 | 2024-11-04 16:48:55.543113+08 | 0 - select * from t1 | 2024-11-04 16:37:33.611937+08 | 2024-11-04 16:37:33.61237+08 | 894 - select * from t1 | 2024-11-04 16:37:33.611803+08 | 2024-11-04 16:37:33.611931+08 | 0 - select max(name) from t1 | 2024-11-04 16:33:25.862634+08 | 2024-11-04 16:33:25.863255+08 | 978 - select max(name) from t1 | 2024-11-04 16:33:25.862076+08 | 2024-11-04 16:33:25.862622+08 | 0 - vacuum t1; | 2024-11-04 16:32:19.123703+08 | 2024-11-04 16:32:19.137293+08 | 0 - select max(?) from t1 | 2024-11-04 16:27:26.614458+08 | 2024-11-04 16:27:26.615534+08 | 2564 -(10 rows) - -``` - -![image-20241104170751474](20241102.assets/image-20241104170751474.png) - -通过上面的查询可知,在statement_history也已经有执行sql的记录,网络消耗的时间为1294us和dbe_perf.statement的值一致。 - -## 总结 - -全链路跟踪能力是对数据库问题定位工具的完善,对于数据库运维的老师来说又是一个好的消息。 在这边文章中我只是带领大家初步了解一下全链路跟踪能力怎么查看,但是详细的内部原理,大家可以参考openGauss官网视频号中对于该功能的详细介绍。 - -## 参考 - -【openGauss 6.0.0 LTS版本特性解读(四) | openGauss 全链路跟踪】https://www.bilibili.com/video/BV1gFSRYKErB?vd_source=0741f9621c39156deebce32bbdc2a50c \ No newline at end of file -- Gitee From f3f5e9117a0f769e02fc5071fe9f068e72314057 Mon Sep 17 00:00:00 2001 From: wangshifei <18734596042@163.com> Date: Tue, 5 Nov 2024 00:54:33 +0000 Subject: [PATCH 10/13] =?UTF-8?q?add=20app/zh/blogs/wangshifei/=E5=B8=A6?= =?UTF-8?q?=E4=BD=A0=E4=BD=93=E9=AA=8C=E4=B8=80=E4=B8=8BopenGauss6.0?= =?UTF-8?q?=E5=85=A8=E9=93=BE=E8=B7=AF=E8=B7=9F=E8=B8=AA=E8=83=BD=E5=8A=9B?= =?UTF-8?q?.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: wangshifei <18734596042@163.com> --- ...7\237\350\270\252\350\203\275\345\212\233" | 130 ++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 "app/zh/blogs/wangshifei/\345\270\246\344\275\240\344\275\223\351\252\214\344\270\200\344\270\213openGauss6.0\345\205\250\351\223\276\350\267\257\350\267\237\350\270\252\350\203\275\345\212\233" diff --git "a/app/zh/blogs/wangshifei/\345\270\246\344\275\240\344\275\223\351\252\214\344\270\200\344\270\213openGauss6.0\345\205\250\351\223\276\350\267\257\350\267\237\350\270\252\350\203\275\345\212\233" "b/app/zh/blogs/wangshifei/\345\270\246\344\275\240\344\275\223\351\252\214\344\270\200\344\270\213openGauss6.0\345\205\250\351\223\276\350\267\257\350\267\237\350\270\252\350\203\275\345\212\233" new file mode 100644 index 00000000..49b3e657 --- /dev/null +++ "b/app/zh/blogs/wangshifei/\345\270\246\344\275\240\344\275\223\351\252\214\344\270\200\344\270\213openGauss6.0\345\205\250\351\223\276\350\267\257\350\267\237\350\270\252\350\203\275\345\212\233" @@ -0,0 +1,130 @@ +# 带你体验一下openGauss6.0全链路跟踪能力 + +在openGauss6.0版本中的可维护性中介绍全链路跟踪能力,主要是追踪并记录sql语句从客户端到数据库服务端网络耗时。这个功能主要是为了解决无法监控网络耗时,因为有些时候,当我们执行一个问题sql执行,有时会发现在服务器端执行没有问题,但是在客户端执行比较慢的问题。现在有全链路跟踪能力,就可以快速的知道一个sql的网络耗时,可以快速的定位sql性能是否与网络相关。 + +## 版本特性描述 + +可维护性:支持全链路跟踪能力 + +- 实现追踪并记录jdbc查询接口执行sql的端到端网络耗时,并记录在数据库dbe_perf.statement视图、statement_history表中。 + +## 支持条件 + +仅当**openGauss server版本和jdbc版本均大于6.0**时,才支持全链路跟踪能力。目前仅有jdbc版本的驱动。另外虽然该特性涉及与jdbc与数据库的交互能力,但是用户只需要在数据库内核设置enable_record_nettime参数是否开启该功能。 + +## enable_record_nettime说明 + +``` +参数说明:控制驱动全链路跟踪功能的开关,on为开,off为关。参数打开后将驱动执行的sql网络链路耗时记录在statement_history表中,通过dbe_perf.statement视图,standby_statement_history函数可以查询链路网络耗时net_trans_time,且wdr报告中TimeModel支持查看net_trans_time。当前仅支持6.0.0以上版本的JDBC驱动。 +该参数属于USERSET类型参数,请参考表1中对应设置方法进行设置。 +取值范围:布尔型 +默认值:off +``` + +## 网络链路耗时查询方式 + +可以查看dbe_perf.statement视图、statement_history表的net_trans_time字段来查看网络链路的耗时,单位是微妙。 + +``` +select query,net_trans_time,last_updated from dbe_perf.statement; +select query,start_time,finish_time,net_trans_time from statement_history; +``` + +## 准备测试用例表 + +在这里我们准备一个简单的测试用例表,来验证简单的增删改查。 + +``` +create table t1(id int primary key,name varchar(100),address varchar(100)); +insert into t1 values(1,'wang1','beijing'); +insert into t1 values(2,'wang2','beijing'); +insert into t1 values(3,'wang3','beijing'); +insert into t1 values(4,'wang4','beijing'); +``` + +## 查看enable_record_nettime默认的值 + +``` +openGauss=# show enable_record_nettime; + enable_record_nettime +----------------------- + off +(1 row) +``` + +## 开启全链路跟踪开关 + +可以使用guc命令来修改enable_record_nettime值为on,开启全链路跟踪功能。另外还需要修改log_min_duration_statement和track_stmt_stat_level参数。 + +**log_min_duration_statement**表示慢SQL阈值,如果为0则全量收集,时间单位为毫秒; + +**track_stmt_stat_level**表示信息捕获的级别,建议设置为track_stmt_stat_level='L0,L0' + +``` +gs_guc reload -N all -I all -c 'enable_record_nettime=on'; +gs_guc reload -N all -I all -c 'log_min_duration_statement=0'; +gs_guc reload -N all -I all -c "track_stmt_stat_level='L0,L0'"; +``` + +## 在客户端执行测试SQL语句 + +``` +select address,max(id) from t1 group by address; +``` + +![image-20241104164958909](20241102.assets/image-20241104164958909.png) + +## 查看dbe_perf.statement视图中的信息 + +``` +openGauss=# select query,net_trans_time,last_updated from dbe_perf.statement where user_name ='test' and query like '%t1%' order by last_updated desc; + query | net_trans_time | last_updated +----------------------------------------------------------------------------+----------------+------------------------------- + select address,max(id) from t1 group by address | 1294 | 2024-11-04 16:50:03.036603+08 + select * from t1 | 1793 | 2024-11-04 16:49:00.123864+08 + select max(name) from t1 | 978 | 2024-11-04 16:37:33.611782+08 + select max(?) from t1 | 2564 | 2024-11-04 16:32:55.269171+08 + vacuum t1; | 0 | 2024-11-04 16:32:19.137282+08 + select count(?) from t1 | 9708 | 2024-11-04 16:11:06.538974+08 + insert into t1 values(?,?,?) | 0 | 2024-11-04 14:53:35.988101+08 + create table t1(id int primary key,name varchar(100),address varchar(100)) | 0 | 2024-11-04 14:53:29.41779+08 +(8 rows) +``` + + + +![image-20241104170854961](20241102.assets/image-20241104170854961.png) + +通过测试结果,可以看出在dbe_perf.statement已经记录刚才执行的sql,并且网络消耗的时间为1294us。 + +## 查看statement_history表中的记录信息 + +``` +openGauss=# select query,start_time,finish_time,net_trans_time from statement_history t where user_name ='test' and query like '%t1%' order by start_time desc limit 10; + query | start_time | finish_time | net_trans_time +-------------------------------------------------+-------------------------------+-------------------------------+---------------- + select address,max(id) from t1 group by address | 2024-11-04 16:49:40.847096+08 | 2024-11-04 16:49:40.848015+08 | 1294 + select address,max(id) from t1 group by address | 2024-11-04 16:49:40.846453+08 | 2024-11-04 16:49:40.847074+08 | 0 + select * from t1 | 2024-11-04 16:48:55.543124+08 | 2024-11-04 16:48:55.543701+08 | 899 + select * from t1 | 2024-11-04 16:48:55.54295+08 | 2024-11-04 16:48:55.543113+08 | 0 + select * from t1 | 2024-11-04 16:37:33.611937+08 | 2024-11-04 16:37:33.61237+08 | 894 + select * from t1 | 2024-11-04 16:37:33.611803+08 | 2024-11-04 16:37:33.611931+08 | 0 + select max(name) from t1 | 2024-11-04 16:33:25.862634+08 | 2024-11-04 16:33:25.863255+08 | 978 + select max(name) from t1 | 2024-11-04 16:33:25.862076+08 | 2024-11-04 16:33:25.862622+08 | 0 + vacuum t1; | 2024-11-04 16:32:19.123703+08 | 2024-11-04 16:32:19.137293+08 | 0 + select max(?) from t1 | 2024-11-04 16:27:26.614458+08 | 2024-11-04 16:27:26.615534+08 | 2564 +(10 rows) + +``` + +![image-20241104170751474](20241102.assets/image-20241104170751474.png) + +通过上面的查询可知,在statement_history也已经有执行sql的记录,网络消耗的时间为1294us和dbe_perf.statement的值一致。 + +## 总结 + +全链路跟踪能力是对数据库问题定位工具的完善,对于数据库运维的老师来说又是一个好的消息。 在这边文章中我只是带领大家初步了解一下全链路跟踪能力怎么查看,但是详细的内部原理,大家可以参考openGauss官网视频号中对于该功能的详细介绍。 + +## 参考 + +【openGauss 6.0.0 LTS版本特性解读(四) | openGauss 全链路跟踪】https://www.bilibili.com/video/BV1gFSRYKErB?vd_source=0741f9621c39156deebce32bbdc2a50c \ No newline at end of file -- Gitee From 3f20fc53b3e2dde3909d48bcbcb0433fadad1f0d Mon Sep 17 00:00:00 2001 From: wangshifei <18734596042@163.com> Date: Tue, 5 Nov 2024 00:55:03 +0000 Subject: [PATCH 11/13] =?UTF-8?q?=E9=87=8D=E5=91=BD=E5=90=8D=20app/zh/blog?= =?UTF-8?q?s/wangshifei/20241102.assets=20=E4=B8=BA=20app/zh/blogs/wangshi?= =?UTF-8?q?fei/=E5=B8=A6=E4=BD=A0=E4=BD=93=E9=AA=8C=E4=B8=80=E4=B8=8BopenG?= =?UTF-8?q?auss6.0=E5=85=A8=E9=93=BE=E8=B7=AF=E8=B7=9F=E8=B8=AA=E8=83=BD?= =?UTF-8?q?=E5=8A=9B.assets?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../image-20241104164958909.png" | Bin .../image-20241104170751474.png" | Bin .../image-20241104170854961.png" | Bin 3 files changed, 0 insertions(+), 0 deletions(-) rename app/zh/blogs/wangshifei/20241102.assets/image-20241104164958909.png => "app/zh/blogs/wangshifei/\345\270\246\344\275\240\344\275\223\351\252\214\344\270\200\344\270\213openGauss6.0\345\205\250\351\223\276\350\267\257\350\267\237\350\270\252\350\203\275\345\212\233.assets/image-20241104164958909.png" (100%) rename app/zh/blogs/wangshifei/20241102.assets/image-20241104170751474.png => "app/zh/blogs/wangshifei/\345\270\246\344\275\240\344\275\223\351\252\214\344\270\200\344\270\213openGauss6.0\345\205\250\351\223\276\350\267\257\350\267\237\350\270\252\350\203\275\345\212\233.assets/image-20241104170751474.png" (100%) rename app/zh/blogs/wangshifei/20241102.assets/image-20241104170854961.png => "app/zh/blogs/wangshifei/\345\270\246\344\275\240\344\275\223\351\252\214\344\270\200\344\270\213openGauss6.0\345\205\250\351\223\276\350\267\257\350\267\237\350\270\252\350\203\275\345\212\233.assets/image-20241104170854961.png" (100%) diff --git a/app/zh/blogs/wangshifei/20241102.assets/image-20241104164958909.png "b/app/zh/blogs/wangshifei/\345\270\246\344\275\240\344\275\223\351\252\214\344\270\200\344\270\213openGauss6.0\345\205\250\351\223\276\350\267\257\350\267\237\350\270\252\350\203\275\345\212\233.assets/image-20241104164958909.png" similarity index 100% rename from app/zh/blogs/wangshifei/20241102.assets/image-20241104164958909.png rename to "app/zh/blogs/wangshifei/\345\270\246\344\275\240\344\275\223\351\252\214\344\270\200\344\270\213openGauss6.0\345\205\250\351\223\276\350\267\257\350\267\237\350\270\252\350\203\275\345\212\233.assets/image-20241104164958909.png" diff --git a/app/zh/blogs/wangshifei/20241102.assets/image-20241104170751474.png "b/app/zh/blogs/wangshifei/\345\270\246\344\275\240\344\275\223\351\252\214\344\270\200\344\270\213openGauss6.0\345\205\250\351\223\276\350\267\257\350\267\237\350\270\252\350\203\275\345\212\233.assets/image-20241104170751474.png" similarity index 100% rename from app/zh/blogs/wangshifei/20241102.assets/image-20241104170751474.png rename to "app/zh/blogs/wangshifei/\345\270\246\344\275\240\344\275\223\351\252\214\344\270\200\344\270\213openGauss6.0\345\205\250\351\223\276\350\267\257\350\267\237\350\270\252\350\203\275\345\212\233.assets/image-20241104170751474.png" diff --git a/app/zh/blogs/wangshifei/20241102.assets/image-20241104170854961.png "b/app/zh/blogs/wangshifei/\345\270\246\344\275\240\344\275\223\351\252\214\344\270\200\344\270\213openGauss6.0\345\205\250\351\223\276\350\267\257\350\267\237\350\270\252\350\203\275\345\212\233.assets/image-20241104170854961.png" similarity index 100% rename from app/zh/blogs/wangshifei/20241102.assets/image-20241104170854961.png rename to "app/zh/blogs/wangshifei/\345\270\246\344\275\240\344\275\223\351\252\214\344\270\200\344\270\213openGauss6.0\345\205\250\351\223\276\350\267\257\350\267\237\350\270\252\350\203\275\345\212\233.assets/image-20241104170854961.png" -- Gitee From 6a874a80eb9c73d743c5a79b6be3ae15e2f42647 Mon Sep 17 00:00:00 2001 From: wangshifei <18734596042@163.com> Date: Tue, 5 Nov 2024 00:56:17 +0000 Subject: [PATCH 12/13] =?UTF-8?q?=E9=87=8D=E5=91=BD=E5=90=8D=20app/zh/blog?= =?UTF-8?q?s/wangshifei/=E5=B8=A6=E4=BD=A0=E4=BD=93=E9=AA=8C=E4=B8=80?= =?UTF-8?q?=E4=B8=8BopenGauss6.0=E5=85=A8=E9=93=BE=E8=B7=AF=E8=B7=9F?= =?UTF-8?q?=E8=B8=AA=E8=83=BD=E5=8A=9B.assets=20=E4=B8=BA=20app/zh/blogs/w?= =?UTF-8?q?angshifei/20241102.assets?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../20241102.assets/image-20241104164958909.png | Bin .../20241102.assets/image-20241104170751474.png | Bin .../20241102.assets/image-20241104170854961.png | Bin 3 files changed, 0 insertions(+), 0 deletions(-) rename "app/zh/blogs/wangshifei/\345\270\246\344\275\240\344\275\223\351\252\214\344\270\200\344\270\213openGauss6.0\345\205\250\351\223\276\350\267\257\350\267\237\350\270\252\350\203\275\345\212\233.assets/image-20241104164958909.png" => app/zh/blogs/wangshifei/20241102.assets/image-20241104164958909.png (100%) rename "app/zh/blogs/wangshifei/\345\270\246\344\275\240\344\275\223\351\252\214\344\270\200\344\270\213openGauss6.0\345\205\250\351\223\276\350\267\257\350\267\237\350\270\252\350\203\275\345\212\233.assets/image-20241104170751474.png" => app/zh/blogs/wangshifei/20241102.assets/image-20241104170751474.png (100%) rename "app/zh/blogs/wangshifei/\345\270\246\344\275\240\344\275\223\351\252\214\344\270\200\344\270\213openGauss6.0\345\205\250\351\223\276\350\267\257\350\267\237\350\270\252\350\203\275\345\212\233.assets/image-20241104170854961.png" => app/zh/blogs/wangshifei/20241102.assets/image-20241104170854961.png (100%) diff --git "a/app/zh/blogs/wangshifei/\345\270\246\344\275\240\344\275\223\351\252\214\344\270\200\344\270\213openGauss6.0\345\205\250\351\223\276\350\267\257\350\267\237\350\270\252\350\203\275\345\212\233.assets/image-20241104164958909.png" b/app/zh/blogs/wangshifei/20241102.assets/image-20241104164958909.png similarity index 100% rename from "app/zh/blogs/wangshifei/\345\270\246\344\275\240\344\275\223\351\252\214\344\270\200\344\270\213openGauss6.0\345\205\250\351\223\276\350\267\257\350\267\237\350\270\252\350\203\275\345\212\233.assets/image-20241104164958909.png" rename to app/zh/blogs/wangshifei/20241102.assets/image-20241104164958909.png diff --git "a/app/zh/blogs/wangshifei/\345\270\246\344\275\240\344\275\223\351\252\214\344\270\200\344\270\213openGauss6.0\345\205\250\351\223\276\350\267\257\350\267\237\350\270\252\350\203\275\345\212\233.assets/image-20241104170751474.png" b/app/zh/blogs/wangshifei/20241102.assets/image-20241104170751474.png similarity index 100% rename from "app/zh/blogs/wangshifei/\345\270\246\344\275\240\344\275\223\351\252\214\344\270\200\344\270\213openGauss6.0\345\205\250\351\223\276\350\267\257\350\267\237\350\270\252\350\203\275\345\212\233.assets/image-20241104170751474.png" rename to app/zh/blogs/wangshifei/20241102.assets/image-20241104170751474.png diff --git "a/app/zh/blogs/wangshifei/\345\270\246\344\275\240\344\275\223\351\252\214\344\270\200\344\270\213openGauss6.0\345\205\250\351\223\276\350\267\257\350\267\237\350\270\252\350\203\275\345\212\233.assets/image-20241104170854961.png" b/app/zh/blogs/wangshifei/20241102.assets/image-20241104170854961.png similarity index 100% rename from "app/zh/blogs/wangshifei/\345\270\246\344\275\240\344\275\223\351\252\214\344\270\200\344\270\213openGauss6.0\345\205\250\351\223\276\350\267\257\350\267\237\350\270\252\350\203\275\345\212\233.assets/image-20241104170854961.png" rename to app/zh/blogs/wangshifei/20241102.assets/image-20241104170854961.png -- Gitee From e47475784ce12a63d8c010efd8f9546737ad51d1 Mon Sep 17 00:00:00 2001 From: wangshifei <18734596042@163.com> Date: Tue, 5 Nov 2024 00:57:31 +0000 Subject: [PATCH 13/13] =?UTF-8?q?add=20app/zh/blogs/wangshifei/=E6=89=8B?= =?UTF-8?q?=E6=8A=8A=E6=89=8B=E6=95=99=E4=BD=A0=E5=AE=89=E8=A3=85openGauss?= =?UTF-8?q?6.0=E4=BC=81=E4=B8=9A=E7=89=88=E5=8D=95=E8=8A=82=E7=82=B9-CentO?= =?UTF-8?q?S7.6.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: wangshifei <18734596042@163.com> --- ...215\225\350\212\202\347\202\271-CentOS7.6" | 356 ++++++++++++++++++ 1 file changed, 356 insertions(+) create mode 100644 "app/zh/blogs/wangshifei/\346\211\213\346\212\212\346\211\213\346\225\231\344\275\240\345\256\211\350\243\205openGauss6.0\344\274\201\344\270\232\347\211\210\345\215\225\350\212\202\347\202\271-CentOS7.6" diff --git "a/app/zh/blogs/wangshifei/\346\211\213\346\212\212\346\211\213\346\225\231\344\275\240\345\256\211\350\243\205openGauss6.0\344\274\201\344\270\232\347\211\210\345\215\225\350\212\202\347\202\271-CentOS7.6" "b/app/zh/blogs/wangshifei/\346\211\213\346\212\212\346\211\213\346\225\231\344\275\240\345\256\211\350\243\205openGauss6.0\344\274\201\344\270\232\347\211\210\345\215\225\350\212\202\347\202\271-CentOS7.6" new file mode 100644 index 00000000..3836e689 --- /dev/null +++ "b/app/zh/blogs/wangshifei/\346\211\213\346\212\212\346\211\213\346\225\231\344\275\240\345\256\211\350\243\205openGauss6.0\344\274\201\344\270\232\347\211\210\345\215\225\350\212\202\347\202\271-CentOS7.6" @@ -0,0 +1,356 @@ +# 手把手教你安装openGauss6.0企业版单节点-CentOS7.6 + +这边文章主要是带领初学者安装openGauss6.0企业版单节点,让你快速上手。 + +## 软硬件环境介绍 + +| 软硬件名称 | 配置 | +| ---------- | --------------------------- | +| CPU | X86_64,8C | +| 内存 | 8G | +| 操作系统 | CentOS7.6 | +| Python版本 | Python2.7.5(后期会做更改) | + +## 获取安装包 + +### 用root用户登录主机,并创建存放安装软件的目录 + +``` +[root@ogdb ~]# mkdir -p /opt/software/openGauss +``` + +### 下载安装包 + +从openGauss社区[下载对应版本安装包](https://opengauss.org/zh/download/),在这里我们下载的版本为x86_64架构且操作系统版本为CentOS7.6。将下载的版本上传到/opt/software/openGauss目录下。 + +``` +[root@ogdb openGauss]# ls -ll +total 149764 +-rw-r--r-- 1 root root 153356080 Nov 1 10:01 openGauss-All-6.0.0-CentOS7-x86_64.tar.gz +[root@ogdb openGauss]# +``` + +解压下载的安装包,解压安装包后,继续解压openGauss-OM-6.0.0-CentOS7-x86_64.tar.gz安装包 + +``` +[root@ogdb openGauss]# tar -xvf openGauss-All-6.0.0-CentOS7-x86_64.tar.gz +openGauss-CM-6.0.0-CentOS7-x86_64.tar.gz +openGauss-OM-6.0.0-CentOS7-x86_64.tar.gz +openGauss-Server-6.0.0-CentOS7-x86_64.tar.bz2 +openGauss-CM-6.0.0-CentOS7-x86_64.sha256 +openGauss-OM-6.0.0-CentOS7-x86_64.sha256 +openGauss-Server-6.0.0-CentOS7-x86_64.sha256 +upgrade_sql.tar.gz +upgrade_sql.sha256 +[root@ogdb openGauss]# +[root@ogdb openGauss]# tar -xvf openGauss-OM-6.0.0-CentOS7-x86_64.tar.gz +``` + +修改安装目录权限 + +``` +[root@ogdb ~]# chmod 755 -R /opt/software +``` + +## 配置安装环境 + +### 配置环境参数 + +- 修改SELINUX值 + +``` +vim /etc/selinux/config +--修改SELINUX值为disabled,然后保存并退出 +SELINUX=disabled +``` + +重启操作系统 + +``` +reboot +``` + +- 关闭防火墙 + +先查看当前防火墙的状态 + +``` +[root@ogdb ~]# systemctl status firewalld +● firewalld.service - firewalld - dynamic firewall daemon + Loaded: loaded (/usr/lib/systemd/system/firewalld.service; disabled; vendor preset: enabled) + Active: active (running) since Fri 2024-11-01 14:05:03 CST; 1s ago + Docs: man:firewalld(1) + Main PID: 21392 (firewalld) + Tasks: 2 + CGroup: /system.slice/firewalld.service + └─21392 /usr/bin/python -Es /usr/sbin/firewalld --nofork --nopid + +Nov 01 14:05:03 ogdb systemd[1]: Starting firewalld - dynamic firewall daemon... +Nov 01 14:05:03 ogdb systemd[1]: Started firewalld - dynamic firewall daemon. +[root@ogdb ~]# +``` + +若防火墙状态显示为active (running),则表示防火墙未关闭,请执行下面关闭防火墙的命令;否则跳过下面的步骤 + +关闭防火墙并禁止开机重启 + +``` +systemctl disable firewalld +systemctl stop firewalld +``` + +- 设置字符集参数 + +``` +[root@ogdb ~]# cat >> /etc/profile < export LANG=en_US.UTF-8 +> EOF +``` + +执行命令使得配置生效 + +``` +[root@ogdb ~]# source /etc/profile +``` + +### 使用yum安装系统依赖项 + +备份原来的yum配置文件 + +``` +[root@ogdb yum.repos.d]# mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.bak +``` + +下载可用源的repo文件,在这里我们https://mirrors.huaweicloud.com/repository/conf获取服务器对应的repo配置文件CentOS-7-anon.repo + +``` +[root@ogdb yum.repos.d]# curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.huaweicloud.com/repository/conf/CentOS-7-anon.repo + % Total % Received % Xferd Average Speed Time Time Time Current + Dload Upload Total Spent Left Speed +100 1811 0 1811 0 0 2253 0 --:--:-- --:--:-- --:--:-- 2252 +``` + +执行命令,安装所需要的依赖包 + +``` +yum install -y libaio-devel readline-devel expect python3 +``` + +### 修改Python版本 + +1. 由于openGauss安装所需要用到python-3.x命令,但是centos7.6版本默认python版本为python-2.7.x,因此需要切换到python-3.x。 + +2. 备份python文件 + + ``` + [root@ogdb bin]# cd /usr/bin + [root@ogdb bin]# mv python python.bak + ``` + +3. 建立python3的软链接 + + ``` + ln -s python3 /usr/bin/python + ``` + +4. 验证python版本 + + ``` + [root@ogdb bin]# python -V + Python 3.6.8 + ``` + + 官方对python版本为CentOS:支持>=Python 3.6.X且<=Python 3.10.X,可知符合要求。 + +## 安装数据库 + +### 创建XML配置文件 + +安装openGauss前需要创建cluster_config.xml文件。cluster_config.xml文件包含部署openGauss的服务器信息、安装路径、IP地址以及端口号等。用于告知openGauss如何部署。用户需根据不同场景配置对应的XML文件。 + +用root用户切换到安装目录 + +``` +cd /opt/software/openGauss +``` + +创建XML配置文件,用于数据库安装 + +``` +vi cluster_config.xml +``` + +将一下的内容粘贴到上面的文件中。 + +``` + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +``` + +### 执行初始化脚本 + +执行预安装初始化命令 + +``` +cd /opt/software/openGauss/script +./gs_preinstall -U omm -G dbgrp -X /opt/software/openGauss/cluster_config.xml +``` + +创建omm用户,对omm用户建立互信,并设置密码 + +``` +Are you sure you want to create the user[omm] (yes/no)? yes +Please enter password for cluster user. +Password: +Please enter password for cluster user again. +Password: +Generate cluster user password files successfully. +``` + +在结尾我们可以看到如下信息,就表示初始化安装完成。 + +``` +Successfully set finish flag. +Preinstallation succeeded. +``` + +### 执行安装 + +切换到omm用户 + +``` +[root@ogdb script]# su - omm +Last login: Fri Nov 1 15:23:20 CST 2024 +[omm@ogdb ~]$ +``` + +切换到目录/opt/software/openGauss/script,然后使用gs_install安装openGauss + +``` +cd /opt/software/openGauss/script +gs_install -X /opt/software/openGauss/cluster_config.xml + +``` + +在安装的过程中需要输入数据库的密码,密码要求一定的复杂度,请记住输入的密码 + +``` +--数据库密码 +openGauss2024 +``` + +安装日志 + +``` +[omm@ogdb script]$ gs_install -X /opt/software/openGauss/cluster_config.xml +Parsing the configuration file. +Successfully checked gs_uninstall on every node. +Check preinstall on every node. +Successfully checked preinstall on every node. +Creating the backup directory. +Successfully created the backup directory. +begin deploy.. +Installing the cluster. +begin prepare Install Cluster.. +Checking the installation environment on all nodes. +begin install Cluster.. +Installing applications on all nodes. +Successfully installed APP. +begin init Instance.. +encrypt cipher and rand files for database. +Please enter password for database: +Please repeat for database: +[GAUSS-50322] : Failed to encrypt the password for databaseError: + Try "gs_guc --help" for more information. +Invalid password,it must contain at least eight characters + +Please enter password for database: +Please repeat for database: +begin to create CA cert files +The sslcert will be generated in /opt/openGauss/app/share/sslcert/om +NO cm_server instance, no need to create CA for CM. +Non-dss_ssl_enable, no need to create CA for DSS +Cluster installation is completed. +Configuring. +Deleting instances from all nodes. +Successfully deleted instances from all nodes. +Checking node configuration on all nodes. +Initializing instances on all nodes. +Updating instance configuration on all nodes. +Check consistence of memCheck and coresCheck on database nodes. +Configuring pg_hba on all nodes. +Configuration is completed. +The cluster status is Normal. +Successfully started cluster. +Successfully installed application. +end deploy.. +``` + +## 数据库使用 + +在安装完成后,数据库服务器是默认启动的 + +切换到omm用户 + +``` +su - omm +``` + +连接数据库,在这里的端口使用的默认端口15400,因此未指定端口 + +``` +[omm@ogdb script]$ gsql -r +gsql ((openGauss 6.0.0 build aee4abd5) compiled at 2024-09-29 18:38:08 commit 0 last mr ) +Non-SSL connection (SSL connection is recommended when requiring high-security) +Type "help" for help. + +openGauss=# +``` + +到这里我们的openGauss6.0企业版单节点部署已经完成,希望你体验openGauss的旅程一帆风顺。 + +## 参考 + +https://docs.opengauss.org/zh/docs/6.0.0/docs/InstallationGuide/%E4%BC%81%E4%B8%9A%E7%89%88%E5%AE%89%E8%A3%85.html \ No newline at end of file -- Gitee