GaussDB 运维案例集

举报
GaussDB 数据库 发表于 2025/12/05 09:22:29 2025/12/05
【摘要】 目  录1 DN动态内存使用满导致DN主备切换2 iptables策略限制导致实例升级报错3 修改bashrc导致om-agent升级失败4 目录权限问题导致DN异常5 2025-11

  

1 DN动态内存使用满导致DN主备切换

2 iptables策略限制导致实例升级报错

3 修改bashrc导致om-agent升级失败

4 目录权限问题导致DN异常

5 2025-11

5.1 业务SQL包含自定义function,通过hint方式添加query_dop,smp不生效

5.2 JDBC导入和gsql导入在insert,replace,duplicate方式性能差异

5.3 主备切换时间长问题分析

5.4 主机流控导致大量业务超时并且无法新建连接

5.5 业务分布键选择不合理导致数据分布不均匀

5.6 DN发生主备切换问题定位


1、DN动态内存使用满导致DN主备切换

  • 故障现象

客户反馈,在05:00--10:31之间GaussDB集中式在DN主备切换。

  • 适用版本

GaussDB全部版本。

  • 告警

DN主备切换。

  • 业务影响

业务闪断,1min内恢复。

  • 故障原因

l   主备切换问题,通常先找到主备切换的节点,即原主DN,新主DN分别是哪个DN

l   然后先从cm_server主、cm_ctl等日志分析,确认主备切换的命令是由cm_server下发还是手动下发。

l   最后如果是cm_server下发主备切换的命令,通常是原主DN异常,则分析原主DN 异常原因。

  • 处理办法

步骤 1     确认DN主备切换时间点。

查看cm_server主日志,搜索关键词“Failover message has sent to instance”,从日志中发现,2024-04-23 05:02:34cm_server下发命令,将dn_6002切换为主DN

cd $GAUSSLOG/cm/cm_server

vim cm_server-yyyy-mm-dd_******-current.log

image007.jpg

继续查看cm_server主日志,搜索关键词“send switchover to instance”,发现在2024-04-23 10:31:21,手工下发了switchover命令,将dn_6001切换为主。

11.png

经以上分析,2024-04-23 05:02:34因为dn_6001的某些故障,cm_server将主DN切换为dn_60022024-04-23 10:31:21手动下发switchover命令将dn_6001切换为主。步骤 2     定位发生主备切换原因。

查看DN进程,发现进程在05:02发生重启。

ps ux|grep dn

12.png

步骤 3     查看是否生成ffic日志。

进入日志目录,发现存在ffic日志。

cd $GAUSSLOG/ffic_log

步骤 4     分析ffic日志。

查看ffic_log日志,发现dn_6001因为发生oom,被AI Watchdog杀掉进程,从而触发主备切换。

14.png

步骤 5     查看dn_6001日志。

搜索关键词,AI Watchdog,发现是因为动态内存上涨,触发AI Watchdog主备切换。

cd $GAUSSLOG/pg_log/dn_6001

vim postgresql-yyyy-mm-dd_******.log

15.png

 步骤 6     查看动态内存使用情况。

查看监控指标,动态内存使用率瞬间冲高。

16.png步骤 7     查看dn_6001动态内存上下文根。

发现hashBatchContext上下文根动态内存使用高,判断可能为大的查询,其中的hash关联占用动态内存高。

cd $GAUSSLOG/mem_log/dn_6001_6002_6003

17.png

步骤 8     查找动态内存占用高的SQL语句。

发现占用动态内存高的SQL语句为insert into语句,该语句存在大量的关联查询,在执行该语句时发生申请内存失败,报错信息为:memory is temporarily unavailable

cd $GAUSSLOG/pg_log/dn_6001

zgrep -i debug_query_id postgresql-yyyy-mm-dd_******.log.zg | awk -F 'consuming about' '{print $2}'|sort -nk1

181.png

182.png

步骤 9     优化insert into语句。

----结束

2、iptables策略限制导致实例升级报错

  • 故障现象

客户进行实例升级,任务流报错,升级失败,如下图所示。

201.png

202.png

  • 适用版本

GaussDB全部版本。

  • 业务影响

l   管控任务流报错,无影响。

l   内核任务流报错,自动回滚成功,无业务影响,运维功能、备份可能会受影响。

l   内核任务流报错,自动回滚失败,集群状态可能异常,影响业务。

  • 故障原因

根据报错任务流时间,147秒报错,说明升级任务流可能还没有下发内核,可能在om_agent前置校验阶段报错。

  • 处理方法

步骤 1     根据升级报错任务流,找到命令下发节点。如下图,单击“操作 > 修改context”,找到“NODE_ID”。

211.png

212.png步骤 2     根据NODE_ID,找到对应节点,登录到节点后台。

步骤 3     切换到Ruby用户,加载环境变量,执行如下命令,查看升级日志。

ll $GAUSSLOG/om/gs_upgradectl_2025*.log

23.png

步骤 4     发现节点上没有产生内核升级日志,说明升级动作还没有到内核侧,返回查看om_agent的日志。

步骤 5     执行如下命令,查看om_agent的升级日志。

vim /home/Ruby/log/om_agent/agent.log

步骤 6     搜索报错时间点前后有没有“ERRORfailed”等报错信息。

26.png

步骤 7     根据报错日志分析,检查数据库连接失败:Check database connection failed。根据报错日志“could not connect to server: Operation now in progress Is the server running on host "127.0.0.1" and accepting TCP/IP connections on port 8000”分析,怀疑是gsql连接数据库报错。

步骤 8     在数据库节点执行如上命令,指定-h 127.0.0.1不通,不指定可以连上,怀疑是127.0.0.1不通。

l   指定-h 127.0.0.1

281.png

l   不指定-h 127.0.0.1

282.png

步骤 9     执行如下命令,测试127.0.0.1的连通性,连接失败。

curl -kv 127.0.0.1 8000

29.png

步骤 10     通过如下命令检查数据库连通性,是,指定-h 127.0.0.1

gsql -d postgres -p $port -h 127.0.0.1 -U rdsAdmin -W $password -m -c 'select 1;'

步骤 11     127.0.0.1不通,怀疑是设置了iptable策略,root用户下执行如下命令查看iptable策略。

iptables -L 

2110.png

步骤 12     如上图,iptables策略存在一条策略限制了127.0.0.1访问。

步骤 13     执行如下命令删除限制127.0.0.1的策略。

iptables -D INPUT -p all -s 127.0.0.1/24  -j REJECT 

2130.png

 步骤 14     执行如下命令,测试127.0.0.1的连通性,连接成功。

curl -kv 127.0.0.1 8000

2140.png

  步骤 15     通过gsql连接,也可以连接成功。

2150.png

 步骤 16     管控界面重试任务流,升级成功。

2160.png

2161.png

----结束


3、修改bashrc导致om-agent升级失败

  • 故障现象

通过TPOPS平台,升级GaussDB实例,升级报错,查看升级任务流,升级子任务om-agent失败。

301.png

  • 适用版本

GaussDB全部版本。

  • 业务影响

升级失败。

  • 故障原因

实例节点上,/home/Ruby/.bashrc 该文件为环境配置文件,该文件在实例安装成功后手动添加了 source ~/gauss_env_file 环境变量 ,导致升级om_agent时,自动加载了GAUSSHOME,使其获取到了GAUSSHOME/bin目录下的openssl,正常要求使用操作系统自带的openssl来生成客户端和服务端的证书和私钥。因为环境变量加载的的openssl路径不对,所以报错证书和私钥不匹配,无法正常启动om_agent进程,导致升级失败。

  • 处理办法步骤 1     查看om_agent日志,提示om_agent拉起失败。

310.png步骤 2     通过 ps -ux 查看 om_agent 进程是否拉起,未拉起,手动尝试拉起om_agent, 提示ssl证书相关错误。

320.png

步骤 3     查看.bashrc 环境变量,发现手动添加了 source ~/gauss_env_file

330.png

步骤 4     登录实例每个节点,去掉 .bashrc 中手动添加的环境变量 source \~/gauss_env_file ,然后重做任务流。

----结束

4、录权限问题导致DN异常

  • 故障现象

复现案例:集群升级完后一个DN状态为down

cm_ctl query -Cv

400.png

  • 适用版本

GaussDB全部版本。

  • 业务影响

所有CN/DN权限异常,会导致数据库无法正常启动。

  • 故障原因

升级过程中需要重启DNDN数据目录由于权限问题无法正常启动。

  • 处理办法

步骤 1     查看DN异常节点om_agentcm_agentcm_server等守护进程无异常。

ps ux

410.png

步骤 2     查看cm_agent进程日志打印有拉起动作但是未正常拉起,排除CMA异常。

cd $GAUSSLOG/cm/cm_agent
vim cm_agent-*current.log
StartAndStop ASYN LOG: BuildStartCommand 0
StartAndStop ASYN LOG: DN START system(command:/usr/local/core/app/bin/gaussdb    -D /var/lib/engine/data1/data/dn_6002 -M pending >> "/var/lib/engine/data1/log/Ruby/cm/cm_agent/system_call-current.log" 2>&1 &), try 4
StartAndStop ASYN LOG: the dn(id:6002) instance restarts counts: 66 in 10 min, 66 in hour.
DnStatus6002 ASYN ERROR: [get_connection: 1446]: fail to read pid file (/var/lib/engine/data1/data/dn_6002/postmaster.pid).
DnStatus6002 ASYN ERROR: failed to connect to datanode:/var/lib/engine/data1/data/dn_6002
DnStatus6002 ASYN ERROR: DatanodeStatusCheck failed, ret=-1
DnStatus6002 ASYN LOG: set 6002 on offline.
CheckProcess ASYN LOG: process (gaussdb) is not running, path is [[/var/lib/engine/data1/data/dn_6002]: [/var/lib/engine/data1/data/dn_6002]], haveFound is 0
CoreDumpCheck ASYN LOG: gaussdb state file "/var/lib/engine/data1/data/dn_6002/gaussdb.state" is not exist, could not get the build infomation: No such file or directory
StartAndStop ASYN ERROR: error.dn is 6002 ret=-1
TpNetReportDnGroupInfoMain ASYN LOG: tp net dn report dn group [0] to cms.
DnStatus6002 ASYN ERROR: [get_connection: 1446]: fail to read pid file (/var/lib/engine/data1/data/dn_6002/postmaster.pid).
DnStatus6002 ASYN ERROR: failed to connect to datanode:/var/lib/engine/data1/data/dn_6002
DnStatus6002 ASYN ERROR: DatanodeStatusCheck failed, ret=-1
DnStatus6002 ASYN LOG: set 6002 on offline.

420.png

步骤 3     查看system_call日志发现打印数据目录权限不足。

cd $GAUSSLOG/cm/cm_agent
vim system_call-current.log
LOG:  assign g_instance_enable_dcf=0
LOG:  configuration file "/var/lib/engine/data1/data/dn_6002/gaussdb.conf" contains errors; unaffected changes were applied
CAUSE:  Error from config file occurs and unaffected changes were applied.
ACTION:  Use correct config file.
FATAL:  data directory "/var/lib/engine/data1/data/dn_6002" has group or world access
DETAIL:  Permissions should be u=rwx (0700).
CAUSE:  The data directory has group or world access.
ACTION:  Add the user to the group or world of the data directory.

430.png

步骤 4     查看该DN数据目录权限为701异常。

440.png

 步骤 5     手动将DN数据目录恢复为700权限。

450.png

 步骤 6     集群状态恢复。

460.png

----结束

5、2025-11

5.1 业务SQL包含自定义function,通过hint方式添加query_dop,smp不生效

  • 问题现象

业务sql执行时间较长,需要通过smp增加并行提升执行效率,通过hint 方式, 发现query_dop 不生效。以下是sql及对应执行计划、相关表表结构。

执行计划

511.png

select表结构

512.png

insert表结构

513.png

  • 技术背景

针对上述SQL案例,smp使用有如下约束条件,如下:

1. function为易变函数,smp不生效, 需要将function调整为i函数。

2. function不能下推到dn执行,smp不生效,需要将function修改为SHIPPABLE

3. 当业务表为分区表且创建了global索引,smp 不生效, 需要将业务表修改为local索引。

function创建规则如下

l 不主动指定 IMMUTABLE | STABLE  默认创建 v 函数 | s 函数,即默认指定 VOLATILE | STABLE

l 不主动指定 SHIPPABLE,默认指定 NOT SHIPPABLE, 即该函数不下推到dn上执行。

pg_proc 字段说明

514.png

515.png

验证如下

l 不主动指定 IMMUTABLE | STABLE  默认创建 v 函数,即默认指定 VOLATILE

l不主动指定 SHIPPABLE,默认指定 NOT SHIPPABLE, 即该函数不下推到dn上执行。

gaussdb=> CREATE FUNCTION func1 RETURN integer
gaussdb->     AS  
gaussdb$>     BEGIN
gaussdb$>         RETURN 2;
gaussdb$>     END;
gaussdb$>     /
CREATE FUNCTION
 
--创建function , 默认是v 函数
gaussdb=> select proname, provolatile, proshippable  from pg_proc where proname = 'func1';
 proname | provolatile | proshippable 
---------+-------------+--------------
 func1   | v           | f
  • 验证案例

1. select 查询结果中使用到了v函数(易变 volatile),smp将不生效,需调整为i (不可变的 immutable) 函数或者s(稳定的 stable)函数。

gaussdb=> CREATE FUNCTION func1 RETURN integer
gaussdb->     AS  
gaussdb$>     BEGIN
gaussdb$>         RETURN 2;
gaussdb$>     END;
gaussdb$>     /
CREATE FUNCTION
 
--创建function , 默认是v 函数
gaussdb=> select proname, provolatile, proshippable  from pg_proc where proname = 'func1';
 proname | provolatile | proshippable 
---------+-------------+--------------
 func1   | v           | f

gaussdb=> create table stu2 (
gaussdb(> id int ,
gaussdb(> sid int,
gaussdb(> sname int
gaussdb(> );
CREATE TABLE
 
--默认执行计划
gaussdb=> explain select *, func1 AS pk_id  from stu2;
 id |      operation       | E-rows | E-width |    E-costs      
----+----------------------+--------+---------+----------------
  1 | ->  Seq Scan on stu2 |   1945 |      12 | 0.000..515.700
(1 row)
 
 
--smp 不生效
gaussdb=> explain insert /*+ set(query_dop 4) set(enable_force_smp on)*/ into stu1 select * from stu2;
 id |        operation        | E-rows | E-width |    E-costs     
----+-------------------------+--------+---------+----------------
  1 | ->  Insert on stu1      |   1945 |      12 | 0.000..515.700
  2 |    ->  Seq Scan on stu2 |   1945 |      12 | 0.000..515.700
(2 rows)
 
--将 func1 修改为 i 函数
gaussdb=> ALTER FUNCTION func1() IMMUTABLE ;
ALTER FUNCTION
 
gaussdb=> select proname, provolatile, proshippable  from pg_proc where proname = 'func1';
    proname | provolatile | proshippable 
   ---------+-------------+--------------
    func1   | i           | f
   (1 row)
 
 
--smp 生效
gaussdb=> explain select /*+ set(query_dop 4) set(enable_force_smp on)*/ *, func1 AS pk_id  from stu2;
 id |                 operation                  | E-rows | E-width |    E-costs    
----+--------------------------------------------+--------+---------+---------------
  1 | ->  Streaming(type: LOCAL GATHER dop: 1/4) |   1945 |      12 | 0.000..11.992
  2 |    ->  Seq Scan on stu2                    |   1945 |      12 | 0.000..7.362
(2 rows)

2. insert 使用了自定义函数,当函数为STABLE/VOLATILE类型的函数,且函数的属性是NOT SHIPPABLE的时候(不能下推到dn执行),smp将不生效,需要调整函数属性为SHIPPABLE

gaussdb=> CREATE FUNCTION func2 RETURN integer
gaussdb->     AS  
gaussdb$>     BEGIN
gaussdb$>         RETURN 2;
gaussdb$>     END;
gaussdb$>     /
CREATE FUNCTION
 
--创建function , 默认不下推dn执行gaussdb=> select proname, provolatile, proshippable  from pg_proc where proname = 'func2';
 proname | provolatile | proshippable 
---------+-------------+--------------
 func2   | v           | f

gaussdb=> create table stu1 (
gaussdb(> id int ,
gaussdb(> sid int,
gaussdb(> sname int,
gaussdb(> pk_id int  DEFAULT func2()
gaussdb(> );
CREATE TABLE
 
 
gaussdb=> create table stu2 (
gaussdb(> id int ,
gaussdb(> sid int,
gaussdb(> sname int
gaussdb(> );
CREATE TABLE
 
--默认执行计划
gaussdb=> explain insert  into stu1 select * from stu2;
 id |        operation        | E-rows | E-width |    E-costs    
----+-------------------------+--------+---------+---------------
  1 | ->  Insert on stu1      |   1945 |      12 | 0.000..29.450
  2 |    ->  Seq Scan on stu2 |   1945 |      12 | 0.000..29.450
(2 rows)
 
--smp 不生效
gaussdb=> explain insert /*+ set(query_dop 4) set(enable_force_smp on)*/ into stu1 select * from stu2;
    id |        operation        | E-rows | E-width |    E-costs     
   ----+-------------------------+--------+---------+----------------
     1 | ->  Insert on stu1      |   1945 |      12 | 0.000..515.700
     2 |    ->  Seq Scan on stu2 |   1945 |      12 | 0.000..515.700
 
-- 调整 func2 函数属性为SHIPPABLE
gaussdb=> ALTER FUNCTION func2() SHIPPABLE;
ALTER FUNCTION
 
gaussdb=> select proname, provolatile, proshippable  from pg_proc where proname = 'func2';
 proname | provolatile | proshippable 
---------+-------------+--------------
 func2   | v           | t
 
 
-- smp 生效
gaussdb=> explain insert /*+ set(query_dop 4) set(enable_force_smp on)*/ into stu1 select * from stu2;
 id |                 operation                  | E-rows | E-width |    E-costs     
----+--------------------------------------------+--------+---------+----------------
  1 | ->  Streaming(type: LOCAL GATHER dop: 1/4) |      0 |       0 | 0.000..493.613
  2 |    ->  Insert on stu1                      |   1945 |      12 | 0.000..493.613
  3 |       ->  Seq Scan on stu2                 |   1945 |      12 | 0.000..493.613
(3 rows)

3. 分区表创建global 索引不支持smp。需要将分区表调整成普通表或者将global索引修改为local索引。

gaussdb=> create table stu1(
gaussdb(> id int ,
gaussdb(> sid int,
gaussdb(> sname int);
CREATE TABLE
 
gaussdb=> create table stu2 (
gaussdb(> id int ,
gaussdb(> sid int,
gaussdb(> sname int
gaussdb(> ) PARTITION BY RANGE (id) (
gaussdb(>     PARTITION p1 VALUES LESS THAN (200),
gaussdb(>     PARTITION pmax VALUES LESS THAN (MAXVALUE)
gaussdb(> );
CREATE TABLE
 
--创建global 索引
gaussdb=> CREATE INDEX idx_st2 ON stu2(id) GLOBAL;
CREATE INDEX
 
 
--默认执行计划
gaussdb=> explain insert  into stu1 select * from stu2;
 id |               operation                | E-rows | E-width |    E-costs    
----+----------------------------------------+--------+---------+---------------
  1 | ->  Insert on stu1                     |   1945 |      12 | 0.000..29.450
  2 |    ->  Partition Iterator              |   1945 |      12 | 0.000..29.450
  3 |       ->  Partitioned Seq Scan on stu2 |   1945 |      12 | 0.000..29.450
(3 rows)
 
 Predicate Information (identified by plan id) 
-----------------------------------------------
   2 --Partition Iterator
         Iterations: 2
   3 --Partitioned Seq Scan on stu2
         Selected Partitions:  1..2
(4 rows)
 
--smp 不生效
gaussdb=> explain insert /*+ set(query_dop 4) set(enable_force_smp on)*/ into stu1 select * from stu2;
 id |               operation                | E-rows | E-width |    E-costs    
----+----------------------------------------+--------+---------+---------------
  1 | ->  Insert on stu1                     |   1945 |      12 | 0.000..29.450
  2 |    ->  Partition Iterator              |   1945 |      12 | 0.000..29.450
  3 |       ->  Partitioned Seq Scan on stu2 |   1945 |      12 | 0.000..29.450
(3 rows)
 
 Predicate Information (identified by plan id) 
-----------------------------------------------
   2 --Partition Iterator
         Iterations: 2
   3 --Partitioned Seq Scan on stu2
         Selected Partitions:  1..2
(4 rows)
 
--修改索引为本地索引
gaussdb=> DROP INDEX idx_st2;
DROP INDEX
gaussdb=> 
gaussdb=> CREATE INDEX idx_st2 ON stu2(id) LOCAL;
CREATE INDEX
 
--smp 生效
gaussdb=> explain insert /*+ set(query_dop 4) set(enable_force_smp on)*/ into stu1 select * from stu2;
 id |                 operation                  | E-rows | E-width |   E-costs    
----+--------------------------------------------+--------+---------+--------------
  1 | ->  Streaming(type: LOCAL GATHER dop: 1/4) |      0 |       0 | 0.000..7.362
  2 |    ->  Insert on stu1                      |   1945 |      12 | 0.000..7.362
  3 |       ->  Partition Iterator               |   1945 |      12 | 0.000..7.362
  4 |          ->  Partitioned Seq Scan on stu2  |   1945 |      12 | 0.000..7.362
(4 rows)
 
 Predicate Information (identified by plan id) 
-----------------------------------------------
   3 --Partition Iterator
         Iterations: 2
   4 --Partitioned Seq Scan on stu2
         Selected Partitions:  1..2
(4 rows)

结论

1. select 语句中使用的ks_auth.F_IS_IDNO为易变函数,smp不生效,需要调整为i函数。

2. insert 对应的表TMP_WATCHLIST_CLIENT_PRE使用的函数dsc_ora_ext.dsc_fn_sys_guid() 不能下推到dn执行,smp不生效,需要修改为SHIPPABLE

3. T_NOR_CLIENT为分区表且创建了global索引,smp 不生效,需要修改为local索引。

5.2 JDBC导入和gsql导入在insert,replace,duplicate方式性能差异

  • 问题现象

insert插入数据,发现jdbc方式比gsql方式性能差。通过jdbcgsql两种方式,对比以下三种插入数据方式,发现性能确实存在差异。

l   insert into XXX

l   replace into XXX

l   insert into XXX on duplicate XXX;

  • 案例验证

1. gsql方式插入数据并查看耗时

表结构

gaussdb=> create table stu1 (f1 varchar(100),
gaussdb(> f2 varchar(100),
gaussdb(> f3 varchar(100));
CREATE TABLE

插入方式

insert into stu1 values (generate_series(1,200000),generate_series(1,200000), random() *100::decimal(5,2));
 
replace into stu2 values (generate_series(1,200000),generate_series(1,200000), random() *100::decimal(5,2));
 
insert into stu3 values (generate_series(1,200000), generate_series(1,200000), random() *100::decimal(5,2)) on duplicate key update f2 = generate_series(1,200000) + 1, f3=generate_series(1,200000)+1;

执行耗时

521.png

 执行计划

insert into XXX

522.png

replace into XXX

523.png

insert into XXX on duplicate XXX

524.png

jdbc方式插入数据并查看耗时

l insert 方式

525.png

l replace方式

526.png

l insert ...duplicate 方式

527.png

l 执行耗时

528.png

 执行计划

insert into XXX 执行计划

529.png

5291.png

 replace into XXX

5292.png

insert into XXX on duplicate XXX

5293.png

  • 结果差异说明

l   gsql方式:三种方式语义一样,在数据库内部只解析一次,走硬解析,一条语句插入20万数据,所以耗时短。

l   jdbc方式:

a. insert into t_test (a,id,name) values(?,?,?) 走一次硬解析,20万次软解析,jdbc侧使用executeBatch接口调用,在数据库内部体现为执行了20万次insert,发送一次P报文,20万次UE报文,一个prepare语句多次调用,执行execute

b. replace into t_test(id,name,a) values (?,?,?) 使用executeBatch接口批量插入20万数据,向内核发送pue报文,在数据库内部体现为执行了20万次insert,语句走一次硬解析,后边调用uE报文执行20万次,与1相同。replace into语句是先删除后更新,返回影响的结果有两行。

5294.png

c.  insert into t_test (id,name,a) values (?,?,?) on duplicate key update a = (a + ?),使用executeBatch接口批量插入20万数据,在数据库内部体现为执行了20万次insertjdbc调用executeBatch接口向内核发送PUE报文,内部将此语句识别为upsert语句,此类语句不能走gplan计划复用,所以每次执行都会解析计划,耗时长.duplicate语句是原位更新,只影响一行。

5295.png

5.3 主备切换时间长问题分析

  • 问题描述

客户反馈DN主备切换时间长,需要分析原因

  • 分析思路

主备切换时间长,通常是因为各个别DN日志回放未完成导致,可根据日志实际进行分析。

  • 分析过程

1.  查看cm_server主日志,确认cm_server下发升主命令的时间以及下发升主的DN

cd $GAUSSLOG/cm/cm_server

vim cm_server-yyyy-mm-dd_******-current.log

2025-06-20 09:31:13.416(cm_server日志时间差8小时)cm_server主收到上报的dn_6001(原主DN)状态异常,可搜索“ERROR”并根据时间点过滤。

5310.png

2025-06-20 09:31:13.475(cm_server日志时间差8小时)cm_server主分别下发Lock1锁命令,对dn_6004,dn_6003,dn_6002进行加锁,可搜索“Lock1 message has sent to instance”关键词。

5311.png

2.查看dn_6002,dn_6003,dn_6004所在节点的cm_agent日志,确认是否收到cm_server下发的加锁命令。

cd $GAUSSLOG/cm/cm_agent

vim cm_agent-yyyy-mm-dd_******-current.log

 2025-06-20 09:31:13.478 (cm_agent日志时间差8小时)cm_agentdn_6004加锁,但加锁失败,可搜索“set Lock1 to instance”关键词。

5321.png

期间对dn_6003dn_6002也在加锁,也是加锁失败,可搜索“set Lock1 to instance”关键词。

5322.png

5323.png

3. cm_agent加锁失败,进一步查看DN日志,确认DN在执行什么操作。

cd $GAUSSLOG/gs_log/dn_6004

vim gaussdb-yyyy-mm-dd_******.log

查看dn_6004日志,2025-06-20 17:31:13.477 dn_6004未完成回放,可根据时间点搜索。

5331.png

dn_6002dn_6003在同一时间点也是未完成回放,此处省略截图。

4继续查看DN运行日志,确认dn_6002,dn_6003,dn_6004在什么时间完成回放。

cd $GAUSSLOG/gs_log/dn_6004

vim gaussdb-yyyy-mm-dd_******.log

2025-06-20 17:32:31.517dn_6004优先回放日志完成,可搜索“redo_done flag is:[true]”关键词。

5341.png

dn_6002dn_6003在同一时间点未完成回放,此处省略截图。

5. dn_6004优先完成回放,进一步查看cm_server主日志,确认是否下发升主命令以及下发时间。

cd $GAUSSLOG/cm/cm_server

vim cm_server-yyyy-mm-dd_******-current.log

2025-06-20 09:32:32.492(cm_server日志时间差8小时)cm_server主下发dn_6004升主命令,可搜索“Failover message has sent to instance”关键词。

5351.png

6. 查看dn_6004节点的cm_agent日志,确认是否收到dn_6004升主命令以及接收时间。

cd $GAUSSLOG/cm/cm_agent

vim cm_agent-yyyy-mm-dd_******-current.log

2025-06-20 09:32:32.492 (cm_agent日志时间差8小时)cm_agent接受cm_server下发的命令,对dn_6004执行升主操作,可搜索“failover msg from cm_server”关键词。

5361.png

7.查看dn_6004运行日志,确认是否开始升主以及时间点。

cd $GAUSSLOG/gs_log/dn_6004

vim gaussdb-yyyy-mm-dd_******.log

2025-06-20 17:32:32.529dn_6004开始升主,可搜索“Instance to do failover”关键词。

5371.png

8. 继续查看dn_6004运行日志,确认升主完成时间点。

cd $GAUSSLOG/gs_log/dn_6004

vim gaussdb-yyyy-mm-dd_******.log

2025-06-20 09:32:36.808dn_6004开始接受新的连接,可搜索“database system is ready to accept connections”关键词。

5381.png

9. 查看dn_6004所在节点的cm_agent日志,确认dn_6004解锁时间。

cd $GAUSSLOG/cm/cm_agent

vim cm_agent-yyyy-mm-dd_******-current.log

2025-06-20 09:32:39.510 (cm_agent日志时间差8小时)cm_agent解锁dn_6004成功,可搜索“process_unlock_no_primary_command succeed”关键词。

5391.png

  • 根本原因

综上分析,得出主备切换时间长的原因为:

l   dn_6001故障以后,dn_6002,dn_6003,dn_6004日志均与主机存在差距,cm_server分别给dn_6002,dn_6003,dn_6004发下锁DN命令,由于DN回放未完成因此支持锁DN失败,直到2025-06-20 17:32:31.517dn_6004优先回放完成,因此选择dn_6004升主。

l   dn_6004回放耗时:2025-06-20 09:31:13.478--2025-06-20 17:32:31.517,持续78s

l   dn_6004升主耗时:2025-06-20 09:32:32.492--2025-06-20 17:32:39.655,持续7s

因此,主备切换耗时长主要在于回放时间长,回放时间长是由于未开启流控,DN主备之间的RTO高。在升主时先要完成回放再执行升主操作。

  • 解决方案

开启流控:gs_guc reload -Z datanode -N all -I all -c "recovery_time_target=60"

  • 补充说明

流控原理说明:

在备机回放日志的能力跟不上主机时,通过在walsender线程中进行一定时间的sleep来降低日志发送速度,让备机来得及回放已接收的日志。也就是当备机接收日志或者回放日志的能力跟不上主机时,通过强制降低主机的业务性能,来保证主备机的日志差异在一定目标范围。

因此,开启流控,在主机业务压力过大时,会限制主机业务。

5392.png

流控为主机业务压力与RTO两者之间的综合选择,需要根据实际业务特点慎重配置。

GaussDB关键日志目录介绍:

l   GaussDB日志路径为$GAUSSLOG目录

l   CNDN运行日志路径:$GAUSSLOG/gs_log

l   cm_server运行日志:$GAUSSLOG/cm/cm_server

l   cm_agent运行日志:$GAUSSLOG/cm/cm_agent

l   升级、安装日志:$GAUSSLOG/om

5.4 主机流控导致大量业务超时并且无法新建连接

  • 问题现象

客户反馈,1525之前是大量SQL执行超时,从1525开始无法创建连接。

  • 分析思路

l   突然出现SQL超时,可能是因为并发突增和、IO打满、资源打满等,可优先通过监控查看资源使用情况以及并发数。

l   无法新建连接,可能是因为连接数满、连接不释放、中间件连接数满等情况。

  • 问题分析

1.获取业务报错信息。

获取业务报错信息,根据业务连接池机制分析以下报错信息,业务连接池连接数为20,当连接被占满并长时间不释放,业务新建连接失败。因此怀疑业务连接池到数据库的连接未及时释放,继续分析数据库相关指标及日志。

2024-06-13 15:25:02 [traceId:40093804-1545-4937-ab7e-5246d06de9b7] [ERROR] [http-nio-8015-exec-227] [com.cmfchina.fis.capital.apply.job.CapitalJobController:72] -- capitalStatusRefresh>>>fail
org.springframework.transaction.CannotCreateTransactionException: Could not open JDBC Connection for transaction; nested exception is com.alibaba.druid.pool.GetConnectionTimeoutException: wait millis 60000, active 20, maxActive 20, creating 0, createErrorCount 1

2. 查看异常时间段数据库监控指标。

首先查看资源使用情况,6131520分左右,cpu、内存使用率无显著突增,表明资源使用无异常。

5421.png

其次查看会话连接情况,6131520分左右,在线会话数略有升高,活跃会话数有显著升高,由15增加到35,表明数据库连接数增加。

5422.png

5423.png

3. 查看SQL语句分布情况。

dn_6001为主DN,根据SQL语句对比,dn_600198%SQL语句为insert语句。当insert语句占比高的时候,通常可能产生流控,因此继续分析流控情况。

5431.png

4. 查看流控相关指标。

异常时间段产生主机流控,流控时间达到180000s

5432.png

5.查看DN运行日志。

dn_6002,dn_6003均产生流控,同时根据日志,以dn_6002为例,备机接收日志位置为:362E/20A4A000,备机回放位置为:362C/BF72D920,因此表明,备机回放慢导致产生主机流控。

5435.png

6. 分析gs_asp采样数据以及wdr报告。

查询gs_asp采样数据以及wdr报告,发现主要的等待事件为:LOGCTRL_SLEEPwait wal sync,该等待事件表明产生主机流控。

5436.png

5436-1.png

7.查找SQL语句。

跟踪WDR报告分析,执行次数最多的两条SQL语句为:3803763747262602308

5437.png

进一步根据unique_sql_id,定位到产生流控的主要SQL语句为:

1unique_sql_id3803763747INSERT INTO cmf_fis.wind_bondanninf语句;

2unique_sql_id262602308INSERT INTO cmf_fis.t_fis_news_port_rel_dm_v4语句。

  • 根本原因

综上分析:

由于大量的insert语句,主机产生xlog多,由于备机回放速率赶不上主机xlog产生速率,触发了主机流控,进而导致已有连接不释放,因此业务新建连接超时。

  • 解决措施

l   临时解决方案:

通常当产生主机流控,执行以下命令关闭流控,进行应急恢复:

gs_guc reload -Z datanode -N all -I all -c "recovery_time_target=0"

l   长期解决方案:

a.         恢复流控参数阈值为30min

gs_guc reload -Z datanode -N all -I all -c "recovery_time_target=1800"

b.         开启极致RTO,该参数设置后需要重启集群生效。

gs_guc set -Z datanode -N all -I all -c "recovery_parse_workers=2"

gs_guc set -Z datanode -N all -I all -c "recovery_redo_workers=4"

  • 补充说明

l 流控原理说明

在备机回放日志的能力跟不上主机时,通过在walsender线程中进行一定时间的sleep来降低日志发送速度,让备机来得及回放已接收的日志。也就是当备机接收日志或者回放日志的能力跟不上主机时,通过强制降低主机的业务性能,来保证主备机的日志差异在一定目标范围。

因此,关闭流控,可能存在主备机之间的RTO增大,在主机故障时,主备机切换的时长可能增加

5437-1.png

流控为主机业务压力与RTO两者之间的综合选择,需要根据实际业务特点慎重配置。

l 极致RTO说明

普通串行回放:

5437-2.png

极致RTO

xLog日志回放建立多级流水线,提高并发度,提升日志回放速度。

5437-3.png

问题实例CPU利用率均比较低,且产生流控根本原因为备机回放慢导致,因此评估开启极致RTO,可有效提高日志回放速率。

5.5 业务分布键选择不合理导致数据分布不均匀

  • 问题现象

数据磁盘使用率不均衡

5501.png

  • 原因分析

客户环境为分布式环境3C3D,从监控指标分析,dn_6001dn_6002dn_6003分片的磁盘使用率比其他2个分片高。

5502.png

怀疑是数据分布不均匀导致。

  • 分析过程

1. 登录到数据库节点,执行如下命令查看数据盘使用率,数据目data1的使用率10%,其他数据目录均为2%

gs_ssh -c "df -h"

551.png

2. 进入到数据目录data1下,执行如下命令查看文件大小,显示base目录占比最大,怀疑数据分布不均匀。

du -sh *

552.png

3. 执行如下SQL,查询倾斜率较大的表

select * from pgxc_get_table_skewness order by skewratio desc limit 10;

553.png

查询结果可以分析出表“t1”的数据倾斜率为100%,完全倾斜。(一般默认倾斜率大于10%,就代表数据已经倾斜)

4. 执行如下SQL,查看表的数据分布情况

select schemaname,tablename,nodename,pg_size_pretty(dnsize) dnsize,dnsize/(sum(dnsize) over ()) as percent from table_distribution('root','t1');

554.png

根据查询结果可以分析出表“t1”的数据全部分布在dn_6001所在的分片

5.查看表“t1”的分布列为“a,分布方式为hash分布。

555.png

6. 查看表“t1”字段“a”的值,全部为固定值“1001

556.png

综上分析,表“t1”的分布键为固定值,导致数据全部被分布到dn_6001节点,导致该分片所对应的数据目录用率比其他节点高。

处理方法

建议业务调整分布键,使数据均匀的分布到所有节点,参考分布式表的设计规范:GaussDB 文档中心

5.6 DN发生主备切换问题定位

  • 问题现象

GaussDB 实例主备切换

  • 问题分析

1. 16:53:14,DN6002DN6001断联,同时查看DN 主节点,未发现进程异常重启相关文件生成(ffic_log,core文件)。

5601.png

2. 16:53:15cms主与dn主节点,网络检查失败。

5602.png

3. 16:53:23CMS主与DN主节点CMA断联,CMSCMA的连接超时时间受wal_sender_timout参数控制,默认是超过6s连接不上,就会断开连接。

5603.png

4. 同时满足如上两个条件,触发6002升主

5604.png

5. 16:53:30,网络恢复,6001角色上报给cms为主,双主情况下留新主,CMS主下发重启6001命令

5605.png

  • 问题原因

网络闪断导致CMS主节点与 DN主节点CMA断联,dn6002dn6001断联 触发了6002升主。网络恢复后,CMS留新主,重启原主。


【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。