南大通用GBase 8c数据库巡检指南:全方位保障数据库健康与性能

原文链接:www.gbase.cn/community/p...

更多精彩内容尽在南大通用GBase技术社区,南大通用致力于成为用户最信赖的数据库产品供应商。

在现代企业环境中,GBase8c作为一款功能强大的关系型数据库,被广泛应用于各种关键业务场景。为了确保数据库的稳定运行、高效性能和数据安全,定期进行数据库巡检是必不可少的。本文将详细介绍如何通过一系列巡检指标查询和SQL 查询,对GBase 8c数据库进行全面的健康检查。

1. 巡检目标与用户权限

数据库巡检的目的是及时发现潜在问题,优化性能,确保数据的完整性和安全性。为了执行这些巡检任务,我们需要创建一个具备足够权限的数据库用户。以下是一个示例,创建一个名为 db_inspector 的用户,赋予其必要的权限:

sql 复制代码
CREATE USER db_inspector WITH SYSADMIN MONADMIN PASSWORD 'gbase;123';

2. 巡检指标与 SQL 查询

2.1 表空间检查

表空间是 GBase8c中用于存储数据文件的逻辑区域。通过检查表空间的使用情况,可以提前发现存储空间不足的问题。

vbnet 复制代码
SELECT 
   to_char(now(), 'yyyy-mm-dd hh24:mi:ss') AS "巡检时间",
   spcname AS "Name(名称)",
   pg_catalog.pg_get_userbyid(spcowner) AS "Owner(拥有者)",
   pg_catalog.pg_size_pretty(pg_catalog.pg_tablespace_size(oid)) AS "Size(表空间大小)"
FROM pg_catalog.pg_tablespace
ORDER BY 1;

需要关注的指标: 表空间大小

查看表空间大小是否接近存储上限,需提前规划扩容。

2.2 数据库检查

检查各个数据库的大小,排除系统数据库(如 template0、template1和 postgres)。

sql 复制代码
SELECT datname, pg_size_pretty(pg_database_size(oid))
FROM pg_database
WHERE datname NOT IN ('template0', 'template1', 'postgres')
ORDER BY pg_database_size(oid) DESC;

需要关注的指标: 数据库大小

查看数据库大小是否异常增长,需排查是否存在数据堆积或未清理的日志。

2.3 用户检查

检查数据库用户的权限、连接限制和资源配额。

sql 复制代码
SELECT usename, usecreatedb, usesuper, valbegin, valuntil, spacelimit, tempspacelimit, spillspacelimit
FROM pg_user;

需要关注的指标: 用户权限、资源配额

用户权限是否合理分配,是否存在高权限用户滥用资源。

2.4 数据库当前连接数

检查当前连接数与最大连接数的使用情况。

sql 复制代码
SELECT 
   to_char(now(), 'yyyy-mm-dd hh24:mi:ss') AS "巡检时间",
   setting::int8 AS "max_conn(最大连接数)",
   (SELECT count(*) FROM pg_stat_activity) AS "now_conn(当前连接数)",
   setting::int8 - (SELECT count(*) FROM pg_stat_activity) AS "remain_conn(剩余连接数)"
FROM pg_settings
WHERE name = 'max_connections';

需要关注的指标: 当前连接数、最大连接数

当前连接数是否超过最大连接数的 90%,需优化连接池或增加最大连接数。

2.5 当前处于空闲状态的会话数

检查空闲连接数,过多的空闲连接可能占用系统资源。

sql 复制代码
SELECT count(*) 
FROM pg_stat_activity 
WHERE state = 'idle';

2.6 长时间未提交事务会话

检查长时间未提交的事务,可能导致锁表或资源占用。

sql 复制代码
SELECT count(*) 
FROM pg_stat_activity 
WHERE state = 'idle in transaction' AND now() - state_change > INTERVAL '5 mins';

需要关注的指标: 查看当前返回记录会话ID

若大量连接处于空闲状态且长时间未提交,需排查应用逻辑问题。

2.7 占用内存最多的会话 TOP 20

检查占用内存最多的会话,避免内存不足问题。

sql 复制代码
SELECT sessid, pg_size_pretty(sum(totalsize)), pg_size_pretty(sum(freesize))
FROM gs_session_memory_detail
GROUP BY sessid
ORDER BY sum(totalsize) DESC
LIMIT 20;

需要关注的指标: 会话内存

若会话占用内存超过 1GB,需关注该会话的 SQL 查询,必要时进行优化。

2.8 数据库冲突事件检查

检查数据库冲突事件,可能导致数据不一致或性能下降。

sql 复制代码
SELECT * 
FROM pg_stat_database_conflicts 
WHERE datname NOT IN ('template0', 'template1');

2.9 缓冲区命中率查询

检查缓冲区命中率,评估内存使用效率。

scss 复制代码
SELECT sum(n_blocks_hit) / sum(n_blocks_fetched) AS cache_hit_rate FROM dbe_perf.statement;

需要关注的指标: 缓冲区命中率

若缓冲区命中率低于 90%,可能需要增加内存或优化查询。

2.10 复制槽检查

检查复制槽的状态,确保数据同步正常。

sql 复制代码
SELECT * FROM pg_replication_slots;

需要关注的指标: 复制槽状态

复制槽的active 列应为 t,restart_lsn 应持续向前推进。

2.11 节点内存使用情况

检查节点内存使用情况,避免内存不足。

sql 复制代码
SELECT * FROM pg_total_memory_detail;

需要关注的指标: 节点内存

若dynamic_peak_memory 接近max_dynamic_memory,需考虑增加内存。

2.12 检查数据库重要配置

检查关键配置参数,确保符合生产环境要求。

sql 复制代码
SELECT 
   to_char(now(), 'yyyy-mm-dd hh24:mi:ss') AS "巡检时间",
   name, setting
FROM pg_settings
WHERE name IN (
   'data_directory', 'port', 'client_encoding', 'config_file', 'hba_file', 
   'ident_file', 'archive_mode', 'logging_collector', 'log_directory', 
   'log_filename', 'log_truncate_on_rotation', 'log_statement', 
   'log_min_duration_statement', 'max_connections', 'listen_addresses'
)
ORDER BY name;

2.13 检查锁表

检查锁表情况,避免长时间锁表导致的性能问题。

vbnet 复制代码
SELECT 
   to_char(now(), 'yyyy-mm-dd hh24:mi:ss') AS "巡检时间",
   relname AS "relname(表名)",
   b.nspname AS "shemaname(模式名)",
   c.rolname AS "user(用户名)",
   d.locktype AS "locktype(被锁对象类型)",
   d.mode AS "mode(锁类型)",
   d.pid AS "pid(进程id)",
   e.query AS "query(锁表sql)",
   current_timestamp - state_change AS "lock_duration(锁表时长)"
FROM pg_class a
INNER JOIN pg_namespace b ON a.relnamespace = b.oid
INNER JOIN pg_roles c ON a.relowner = c.oid
INNER JOIN pg_locks d ON a.oid = d.relation
LEFT JOIN pg_stat_activity e ON d.pid = e.pid
WHERE d.mode = 'AccessExclusiveLock'
ORDER BY "lock_duration(锁表时长)" DESC;

处理建议: 若发现长时间锁表,可使用SELECT pg_terminate_backend(pid); 终止相关会话。

2.14 检查长事务 TOP5

检查长时间运行的事务,可能导致资源占用或锁表。

sql 复制代码
SELECT 
   to_char(now(), 'yyyy-mm-dd hh24:mi:ss') AS "巡检时间",
   a.datname AS "datname(数据库名)",
   a.pid AS "pid(进程id)",
   b.rolname AS "username(用户名)",
   a.client_addr AS "client_ip(客户端ip)",
   to_char(a.state_change, 'yyyy-mm-dd hh24:mi:ss') AS "state_change(状态变化时间)"
FROM pg_stat_activity a
INNER JOIN pg_roles b ON a.usesysid = b.oid
WHERE a.state IN ('idle in transaction', 'idle in transaction (aborted)')
   AND state_change < current_timestamp - INTERVAL '30 mins'
ORDER BY current_timestamp - state_change DESC
LIMIT 5;

2.15 检查表膨胀 TOP 5

检查表膨胀情况,可能导致性能下降。

sql 复制代码
SELECT 
   to_char(now(), 'yyyy-mm-dd hh24:mi:ss') AS "巡检时间",
   current_database() AS current_database,
   relname AS "table_name(表名)",
   schemaname AS "schema_name(模式名)",
   pg_size_pretty(pg_relation_size('"' || schemaname || '"."' || relname || '"')) AS "table_size(表大小)",
   n_dead_tup AS "n_dead_tup(无效记录数)",
   n_live_tup AS "n_live_tup(有效记录数)",
   to_char(round(n_dead_tup * 1.0 / (n_live_tup + n_dead_tup) * 100, 2), 'fm990.00') AS "dead_rate(无效记录比例%)"
FROM pg_stat_all_tables
WHERE n_live_tup + n_dead_tup <> 0
ORDER BY "dead_rate(无效记录比例%)" DESC
LIMIT 5;

处理建议: 对膨胀表执行 VACUUM ANALYZE 操作。

2.16 检查索引膨胀

检查索引膨胀情况,可能导致查询性能下降。

sql 复制代码
SELECT 
   to_char(now(), 'yyyy-mm-dd hh24:mi:ss') AS "巡检时间",
   current_database() AS db,
   schemaname,
   tablename,
   bs,
   reltuples::bigint AS tups,
   relpages::bigint AS pages,
   otta,
   ROUND(CASE WHEN otta = 0 OR relpages = 0 OR relpages = otta THEN 0.0 ELSE relpages / otta::numeric END, 1) AS tbloat,
   CASE WHEN relpages < otta THEN 0 ELSE relpages::bigint - otta END AS wastedpages,
   CASE WHEN relpages < otta THEN 0 ELSE bs * (relpages - otta)::bigint END AS wastedbytes,
   CASE WHEN relpages < otta THEN '0 bytes' ELSE (bs * (relpages - otta))::bigint || ' bytes' END AS wastedsize
FROM (
   SELECT 
       nn.nspname AS schemaname,
       cc.relname AS tablename,
       COALESCE(cc.reltuples, 0) AS reltuples,
       COALESCE(cc.relpages, 0) AS relpages,
       COALESCE(bs, 0) AS bs,
       COALESCE(CEIL((cc.reltuples * ((datahdr + ma - (CASE WHEN datahdr % ma = 0 THEN ma ELSE datahdr % ma END)) + nullhdr2 + 4)) / (bs - 20::float)), 0) AS otta
   FROM pg_class cc
   JOIN pg_namespace nn ON cc.relnamespace = nn.oid AND nn.nspname <> 'information_schema'
   LEFT JOIN (
       SELECT 
           ma, bs, foo.nspname, foo.relname,
           (datawidth + (hdr + ma - (CASE WHEN hdr % ma = 0 THEN ma ELSE hdr % ma END)))::numeric AS datahdr,
           (maxfracsum * (nullhdr + ma - (CASE WHEN nullhdr % ma = 0 THEN ma ELSE nullhdr % ma END))) AS nullhdr2
       FROM (
           SELECT 
               ns.nspname, tbl.relname, hdr, ma, bs,
               SUM((1 - coalesce(null_frac, 0)) * coalesce(avg_width, 2048)) AS datawidth,
               MAX(coalesce(null_frac, 0)) AS maxfracsum,
               hdr + (
                   SELECT 1 + count(*) / 8
                   FROM pg_stats s2
                   WHERE null_frac <> 0 AND s2.schemaname = ns.nspname AND s2.tablename = tbl.relname
               ) AS nullhdr
           FROM pg_attribute att
           JOIN pg_class tbl ON att.attrelid = tbl.oid
           JOIN pg_namespace ns ON ns.oid = tbl.relnamespace
           LEFT JOIN pg_stats s ON s.schemaname = ns.nspname
               AND s.tablename = tbl.relname
               AND s.inherited = false
               AND s.attname = att.attname,
           (
               SELECT 
                   (SELECT current_setting('block_size')::numeric) AS bs,
                   CASE WHEN SUBSTRING(SPLIT_PART(v, ' ', 2) FROM '"[0-9]+.[0-9]+"%' for '') IN ('8.0', '8.1', '8.2') THEN 27 ELSE 23 END AS hdr,
                   CASE WHEN v ~ 'mingw32' OR v ~ '64-bit' THEN 8 ELSE 4 END AS ma
               FROM (SELECT version() AS v) AS foo
           ) AS constants
           WHERE att.attnum > 0 AND tbl.relkind = 'r'
           GROUP BY 1, 2, 3, 4, 5
       ) AS foo
   ) AS rs ON cc.relname = rs.relname AND nn.nspname = rs.nspname
) AS sml;

建议:索引膨胀可能导致查询性能下降,需定期重建或优化索引。

3. 巡检总结

通过以上巡检指标和 SQL 查询,我们可以全面了解 GBase8c数据库的健康状态和性能表现。定期执行这些巡检任务,可以帮助我们及时发现潜在问题,优化资源配置,确保数据库的稳定运行。建议将这些查询封装为脚本,并通过定时任务定期执行,将结果记录到日志文件中,便于后续分析和回顾。

原文链接:www.gbase.cn/community/p...

更多精彩内容尽在南大通用GBase技术社区,南大通用致力于成为用户最信赖的数据库产品供应商。

相关推荐
Marzlam19 分钟前
Sql Server 索引性能优化 分析以及分表
数据库·性能优化
明月看潮生30 分钟前
青少年编程与数学 02-011 MySQL数据库应用 10课题、记录的操作
数据库·mysql·青少年编程·编程与数学
Gauss松鼠会33 分钟前
GaussDB构建高性能Schema:分布式数据库架构设计与实战
数据库·分布式·sql·数据库架构·gaussdb
小王努力学编程1 小时前
【MySQL篇】索引特性
开发语言·数据库·学习·mysql
手握风云-1 小时前
MySQL数据库精研之旅第二期:库操作的深度探索
数据库
患得患失9492 小时前
【后端】【Django】【ORM】SearchFilter 详解
数据库·django·sqlite
m0_748251522 小时前
【MySQL】深度学习数据库开发技术:使用CC++语言访问数据库
数据库·mysql·数据库开发
weixin_307779132 小时前
稳定运行的以Neo4j图数据库为数据源和目标的ETL性能变差时提高性能方法和步骤
数据库·性能优化·neo4j·etl
小薛博客2 小时前
架构设计之自定义延迟双删缓存注解(上)
java·数据库·redis·缓存
大刀爱敲代码2 小时前
Redis实战常用二、缓存的使用
数据库·redis·缓存