
# 连接数和活跃连接数异常情况定位及处理方法
本章节的所有SQL操作都使用root用户执行。
#### 指标异常说明（影响）
当数据库的连接数达到最大连接数的上限时，后续增加的连接将会被拒绝，同时连接数和活跃连接数的异常变化也在一定程度上可以预示业务变化和数据库状态。
RDS for PostgreSQL提供了数据库连接数和活跃连接数两个监控指标。
- 数据库连接数：当前连接到数据库的后端量。
- 活跃连接数：该指标为统计数据库当前活跃连接数。
 
#### 问题排查思路
以下现象不考虑正常的业务变更情况，如连接池参数修改，业务规模改变等。
如用户无法及时判断自身是否有业务变更，或者突然的业务高并发，可先通过当前数据库连接信息进行反向判断。
- 数据库连接数异常降低后正常 可能原因：数据库断开了连接 ，数据库发生OOM或crash导致数据库异常重启。
  
- 数据库连接数异常增加或者直至连接数满 可能原因：单位时间新建连接数大于关闭的连接数会导致连接数上升。
  
- 存在以下情况，会降低并发性从而导致连接未能及时释放
  - 存在慢SQL
  
  - 存在锁冲突
  
  - 存在长事务
   
 
#### 排查方法
- **查询当前连接信息**
  可通过pg_stat_activity视图中的信息组合排列出想要获取的数据库连接信息。
  以下为示例，使用root用户执行以下SQL：
  ```
  -- 这里以数据库，用户名，客户端IP，状态来分类，以客户端数量倒序排列
  SELECT datname, usename, client_addr, state, count(*) AS client_number 
  FROM pg_stat_activity 
  WHERE state <> 'idle' 
  GROUP BY datname, usename, client_addr, state 
  ORDER BY client_number DESC;
  ```
  从上面的查询结果中，可以看到数量较多的连接从何而来。从而帮助判断可能存在业务变更的模块，也可判断是哪块业务并发高。
  
- **连接数满**
  当数据库无法连接，并有以下错误日志时，说明当前数据库连接数满。
  ```
  FATAL: remaining connection slots are reserved for non-replication superuser connections.
  FATAL: sorry, too many clients already.
  ```
  
- **数据库异常重启检查**
  1. 通过监控指标内存使用率查看内存是否存在变化。
  
  2. 通过[查看或下载错误日志](https://support.huaweicloud.com/usermanual-rds-pg/rds_recent_log.html)功能下载包含对应时间段的错误日志。
  
  3. 通过"killed"或"the database system is in recovery mode"关键字，确认重启发生时间。
   
- **慢SQL**
  慢SQL大部分时候伴随着CPU使用率高，可参考[RDS for PostgreSQL CPU过载定位及处理建议](https://support.huaweicloud.com/usermanual-rds-pg/rds_pg_10_0000.html)中慢SQL的定位方法定位。
  
- **锁冲突**
  1. 通过pg_stat_activity视图和pg_blocking_pids函数查询当前数据库连接的锁状态，使用root用户执行以下SQL。
     ```
     -- 查询当前事务被启动的时间最早的5个PID（某个客户端的连接）的锁状态
     SELECT pg_blocking_pids(pid), array_length(pg_blocking_pids(pid), 1) blocking_num, * 
     FROM pg_stat_activity 
     WHERE pid IN (select pid FROM pg_stat_activity WHERE state <> 'idle' 
     AND xact_start IS NOT NULL ORDER BY xact_start DESC LIMIT 5) 
     AND pid <> pg_backend_pid() 
     ORDER BY blocking_num DESC NULLS LAST;
     ```
     
  
  2. 通过上面的查询结果判断当前连接数是否存在大量的锁冲突，从而导致连接无法释放。
   
- **长事务**
  参考[长事务问题定位及处理方法](https://support.huaweicloud.com/usermanual-rds-pg/rds_pg_08_00010.html)中的定位方法。
  
 
#### 解决方法
- **正常业务变更或业务并发升高**
  为保证数据库健康运行，可提高实例规格来解决问题。
  
- **连接数满**
  临时解决方法：
  1. 通过已存在的root用户连接，执行以下SQL释放无用的空闲连接。 以查询用户user的空闲连接为例，获取pid的SQL如下：
     ```
     select * from pg_stat_activity where state = 'idle' and usename = 'user';
     ```
     释放无用的空闲连接：
     ```
     select pg_terminate_backend(pid);
     ```
     
  
  2. 调高"max_connections"参数值，该参数重启生效。
  
  
  长期解决方法：
  1. 限制业务，降低业务连接。
  
  2. 如果评估业务本身需要很多连接无法继续优化时，可进行规格变更扩大实例规格。
   
- **OOM或crash**
  如果内存使用率长时间处于较高位置，可提高实例规或优化业务系统，减少常驻内存占用。如果由于SQL导致的数据库重启，对SQL进行优化。
  
- **慢SQL**
  定位到对应的慢SQL，对SQL进行优化。
  
- **锁冲突**
  判断连接的客户端业务是否可以断开，可以则及时通过pg_cancel_backend函数断开对应的数据库连接。
  
- **长事务**
  参考[长事务问题定位及处理方法](https://support.huaweicloud.com/usermanual-rds-pg/rds_pg_08_00010.html)中的处理方法。
  
 
