mirror of
https://github.com/Vonng/ddia.git
synced 2024-12-06 15:20:12 +08:00
12 KiB
12 KiB
Monitor
磁盘
磁盘写满问题
- 一个数据库管理员最重要的磁盘监控任务就是确保磁盘不会写满。
- 一个写满了的数据磁盘可能不会导致数据的崩溃,但它肯定会让系统变得不可用。
- 如果保存 WAL 文件的磁盘变满,Server会产生致命错误,可能会关闭。
- 有些文件系统在快满的时候性能会急剧恶化,不要等到磁盘完全满时再行动。
- 可以将WAL和数据目录放到不同的磁盘上。
- 可以通过使用表空间(Tablespace)把一些数据库文件移到其他文件系统上去。
磁盘占用
- 每个表都有一个主要的堆磁盘文件,大多数数据都存储在其中。
- 每个表和索引都存放在单独的磁盘文件里。若超过 1G 字节,则可能多于一个文件。
- 如果一个表有很宽(>2KB)的列, 则存在一个TOAST文件之关联, 用于存储太宽的值。因为Pg里一个页大小8KB,而单个元组不允许跨页,TOAST字段长度用四字节整形表示,最高的两个比特位用于指示Toast,所以单个字段值长度不能超过1G。
监视磁盘
有三种方式监控磁盘空间:
-
人工观察系统目录。
du
,df -h
-
使用
oid2name
模块 -
使用
SQL
函数与系统视图。(推荐)例如
pg_class
中的RelPages
指明了对象使用的Page (8k block)的数目。可用于预估表大小。
常用查询
--查询表占用空间(估计)
-- 页面大小为8k,元组条数为估计值
SELECT relname, relpages, reltuples,
pg_relation_filepath(oid), reltoastrelid
FROM pg_class where relname = 'messages';
-- 查看表索引大小
SELECT c2.relname, c2.relpages
FROM pg_class c, pg_class c2, pg_index i
WHERE c.relname = 'messages' AND
c.oid = i.indrelid AND
c2.oid = i.indexrelid
ORDER BY c2.relname DESC;
-- 查看表大小与索引大小
SELECT
relname,
relpages,
reltuples,
pg_relation_filepath(oid),
pg_size_pretty(pg_relation_size(oid)) AS rel_size,
pg_size_pretty(pg_indexes_size(oid)) AS idx_size,
reltoastrelid
FROM pg_class
WHERE relname = 'poi';
锁
未解决的锁可以通过系统视图 pg_locks
查看
Vacuum进度
目前只有Vacuum命令可以查看执行进度。
pg_stat_progress_vacuum
指标
进程监控
使用Unix工具,可以查看工作中的postgres进程
ps auxww | grep ^postgres
$ ps auxww | grep ^postgres
postgres 15551 0.0 0.1 57536 7132 pts/0 S 18:02 0:00 postgres -i
postgres 15554 0.0 0.0 57536 1184 ? Ss 18:02 0:00 postgres: writer process
postgres 15555 0.0 0.0 57536 916 ? Ss 18:02 0:00 postgres: checkpointer process
postgres 15556 0.0 0.0 57536 916 ? Ss 18:02 0:00 postgres: wal writer process
postgres 15557 0.0 0.0 58504 2244 ? Ss 18:02 0:00 postgres: autovacuum launcher process
postgres 15558 0.0 0.0 17512 1068 ? Ss 18:02 0:00 postgres: stats collector process
postgres 15582 0.0 0.0 58772 3080 ? Ss 18:04 0:00 postgres: joe runbug 127.0.0.1 idle
postgres 15606 0.0 0.0 58772 3052 ? Ss 18:07 0:00 postgres: tgl regression [local] SELECT waiting
postgres 15610 0.0 0.0 58772 3056 ? Ss 18:07 0:00 postgres: tgl regression [local] idle in transaction
例如,空连接会提示[idle]
,begin
的事务会提示idle in transaction
,如果进程在执行某条命令,会显示在进程的名称之中。
其他实用的监控工具包括:ps
,top
,iostat
,vmstat
统计收集
相关选项
name | type | default | comment |
---|---|---|---|
track_activities |
boolean |
true |
启用对每个会话的当前执行命令的信息收集,还有命令开始执行的时间 |
track_activity_query_size |
integer |
1024 |
声明保留的字节数,以跟踪每个活动会话的当前执行命令 |
track_counts |
boolean |
true |
启用在数据库活动上的统计收集,Vacuum需要这个统计 |
track_io_timing |
boolean |
false |
启用对系统 I/O 调用的计时。 |
track_functions |
enum |
none |
指定pl 只跟踪过程语言函数,指定all 跟踪 SQL 和 C 语言函数 |
stats_temp_directory |
string |
pg_stat_tmp |
统计数据临时目录路径 |
- 统计进程通过临时文件将统计数据传递给其他PostgreSQL进程
- 临时的统计信息放在
pg_stat_tmp
目录下,这个目录可以通过RAMDISK获得更好的性能。 - 当服务器关闭时,统计数据的拷贝会放在
pg_stat
目录下。 - 当服务器启动恢复时,所有统计计数器会重置。
查看统计数据
- 统计数据并非实时更新的,每个服务进程只有在闲置前会更新统计计数。所以正在执行的查询和事务不影响计数。
- 收集器本身每隔(PGSTAT_STAT_INTERVAL=500ms)才发送一次新的报告。所以除了 当前进程活动
track_activity
之外的统计指标都不是最新的。 - 在事务中执行的统计查询,统计数据不会发生变化。使用
pg_stat_clear_snapshot()
来获取最新的快照。
系统视图名称
视图名称 | 描述 |
---|---|
pg_stat_archiver |
只有一行,显示有关 WAL 归档进程活动的统计信息。详见pg_stat_archiver。 |
pg_stat_bgwriter |
只有一行,显示有关后台写进程的活动的统计信息。详见pg_stat_bgwriter。 |
pg_stat_database |
每个数据库一行,显示数据库范围的统计信息。详见pg_stat_database。 |
pg_stat_database_conflicts |
每个数据库一行,显示数据库范围的统计信息, 这些信息的内容是关于由于与后备服务器的恢复过程 发生冲突而被取消的查询。详见pg_stat_database_conflicts。 |
pg_stat_all_tables |
当前数据库中每个表一行,显示有关访问指定表的统计信息。详见pg_stat_all_tables。 |
pg_stat_sys_tables |
和pg_stat_all_tables 一样,但只显示系统表。 |
pg_stat_user_tables |
和pg_stat_all_tables 一样,但只显示用户表。 |
pg_stat_xact_all_tables |
和pg_stat_all_tables 相似,但计数动作只在当前事务内发生(还没有被包括在pg_stat_all_tables 和相关视图中)。用于生存和死亡行数量的列以及清理和分析动作在此视图中不出现。 |
pg_stat_xact_sys_tables |
和pg_stat_xact_all_tables 一样,但只显示系统表。 |
pg_stat_xact_user_tables |
和pg_stat_xact_all_tables 一样,但只显示用户表。 |
pg_stat_all_indexes |
当前数据库中的每个索引一行,显示:表OID、索引OID、模式名、表名、索引名、 使用了该索引的索引扫描总数、索引扫描返回的索引记录数、使用该索引的简 单索引扫描抓取的活表(livetable)中数据行数。 当前数据库中的每个索引一行,显示与访问指定索引有关的统计信息。详见pg_stat_all_indexes。 |
pg_stat_sys_indexes |
和pg_stat_all_indexes 一样,但只显示系统表上的索引。 |
pg_stat_user_indexes |
和pg_stat_all_indexes 一样,但只显示用户表上的索引。 |
pg_statio_all_tables |
当前数据库中每个表一行(包括TOAST表),显示:表OID、模式名、表名、 从该表中读取的磁盘块总数、缓冲区命中次数、该表上所有索引的磁盘块读取总数、 该表上所有索引的缓冲区命中总数、在该表的辅助TOAST表(如果存在)上的磁盘块读取总数、 在该表的辅助TOAST表(如果存在)上的缓冲区命中总数、TOAST表的索引的磁盘块读 取总数、TOAST表的索引的缓冲区命中总数。 当前数据库中的每个表一行,显示有关在指定表上 I/O 的统计信息。详见pg_statio_all_tables。 |
pg_statio_sys_tables |
和pg_statio_all_tables 一样,但只显示系统表。 |
pg_statio_user_tables |
和pg_statio_all_tables 一样,但只显示用户表。 |
pg_statio_all_indexes |
当前数据库中每个索引一行,显示:表OID、索引OID、模式名、 表名、索引名、该索引的磁盘块读取总数、该索引的缓冲区命中总数。 当前数据库中的每个索引一行,显示与指定索引上的 I/O 有关的统计信息。详见pg_statio_all_indexes。 |
pg_statio_sys_indexes |
和pg_statio_all_indexes 一样,但只显示系统表上的索引。 |
pg_statio_user_indexes |
和pg_statio_all_indexes 一样,但只显示用户表上的索引。 |
pg_statio_all_sequences |
当前数据库中每个序列对象一行,显示:序列OID、模式名、序列名、序列的磁盘读取总数、序列的缓冲区命中总数。 当前数据库中的每个序列一行,显示与指定序列上的 I/O 有关的统计信息。详见pg_statio_all_sequences。 |
pg_statio_sys_sequences |
和pg_statio_all_sequences 一样,但只显示系统序列(目前没有定义系统序列,因此这个视图总是为空)。 |
pg_statio_user_sequences |
和pg_statio_all_sequences 一样,但只显示用户序列。 |
pg_stat_user_functions |
对于所有跟踪功能,函数的OID,模式,名称,数量 通话总时间,和自我的时间。自我时间是 在函数本身所花费的时间量,总时间包括 它调用函数所花费的时间。时间值以毫秒为单位。 每一个被跟踪的函数一行,显示与执行该函数有关的统计信息。详见pg_stat_user_functions。 |
pg_stat_xact_user_functions |
和pg_stat_user_functions 相似,但是只统计在当前事务期间的调用(还没有被包括在pg_stat_user_functions 中)。 |
pg_stat_progress_vacuum |
每个运行VACUUM 的后端(包括自动清理工作者进程)一行,显示当前的进度。见第 28.4.1 节。 |
常用统计语句
-- 按照拉取数据条数降序,查看所有表。
SELECT * FROM pg_stat_user_tables ORDER BY seq_tup_read DESC;
-- 按照函数调用次数降序,查看所有存储过程调用情况
SELECT * FROM pg_stat_user_functions ORDER BY calls DESC;
-- 查看表使用的buffer
SELECT
relname,
count(*) AS buffers
FROM pg_class c
JOIN pg_buffercache b ON b.relfilenode = c.relfilenode
INNER JOIN pg_database d ON (b.reldatabase = d.oid AND d.datname = current_database())
WHERE c.relname NOT LIKE 'pg%'
GROUP BY c.relname
ORDER BY 2 DESC;
-- 检查表的脏页
SELECT
relname,
b.isdirty
FROM pg_class c
JOIN pg_buffercache b ON b.relfilenode = c.relfilenode
INNER JOIN pg_database d ON (b.reldatabase = d.oid AND d.datname = current_database())
WHERE c.relname NOT LIKE 'pg%'
ORDER BY 2 DESC;