0
点赞
收藏
分享

微信扫一扫

postgresql源码学习(50)—— 小白学习Dtrace追踪源码函数调用


       不知不觉第50篇了,昨天在文章里(https://mp.weixin.qq.com/s/AzBGzYhGxYjSf7Sptj55lQ)学到一个追踪源码执行情况的利器 —— Dtrace,本篇记录下实验和笔记。

一、 解决痛点

      学习以来一直有一个疑惑,如何将pg中执行的SQL语句和源码对应起来?回顾下之前学到的gdb调试方法,看看适用场景,以及不足。

常用调试方法

  • 已知函数名:gdb调试。包括很常用的一些语句例如checkpoint,对应函数名网上都能搜到
  • 慢查询卡在某个特定函数:可以gdb跟踪进程然后查看调用栈
  • 有报错信息:根据报错文本在源码中搜索

如果是业务任意执行的一条语句、出现了某些怪异的现象(例如原文是加长字段长度后其统计信息被删除),如何能知道它究竟调用了pg中的哪些函数?而哪些函数是不符合我们预期的?Dtrace就能解决这个问题。

二、 准备工作

DTrace叫动态追踪(Dynamic Tracing),本身是源于Solaris系统的,无法在Linux中运行 。因为非常好用,有了Linux移植版,名SystemTap。SystemTap 也定义了一种类似的脚本语言,方便用户根据需要自由扩展。更多简介可以

1. 安装SystemTap

我Oracle Linux 7的虚拟机自带了这个工具,如果没有,可以安装以下包

yum -y install systemtap systemtap-runtime

执行hello world测试命令

stap -e 'probe begin{printf("Hello, World"); exit();}'

postgresql源码学习(50)—— 小白学习Dtrace追踪源码函数调用_源码学习

上面那些提示对测试没什么影响,可以不管它。

       如果不能输出Hello, World,则需要根据提示装一些kernel相关的包,注意必须跟操作系统的版本是一致的,不能直接yum安装最新版。

2. 使用--enable-dtrace选项编译安装pg

postgresql源码学习(一)—— 源码编译安装与gdb调试入门_Hehuy

三、 开始测试

准备完终于可以开始测了,就以原文的例子,看看加长字段长度会调用什么函数。

1. Systemtap脚本准备

vi function.c

      脚本内容,process中的路径自行替换,function中的*代表输出所有函数(因为不知道具体有哪些,可以利用通配符缩小范围,例如*Start*)

probe process("/data/postgres/base/14.0/bin/postgres").function("*") {
         printf("%s: %s\n", execname(), ppfunc());
 }

2. 创建测试表

create table t(id int,info varchar(10));
insert into t select n,left(md5(random()::text),10) from generate_series(1,1000) as n;
analyze t;

postgresql源码学习(50)—— 小白学习Dtrace追踪源码函数调用_统计信息_02

3. 执行Systemtap脚本

stap function.c > mylog.txt

postgresql源码学习(50)—— 小白学习Dtrace追踪源码函数调用_Dtrace_03

       红色的提示可以忽略,实际已经装了这个包,并不影响使用,WARNING的信息虽然多,但也不影响使用。

4. 执行加长字段语句

alter table t alter COLUMN info type varchar(20);

这里发现需要另开一个会话才能抓到,直接在原先会话执行一直是些空闲等待的函数

postgresql源码学习(50)—— 小白学习Dtrace追踪源码函数调用_Dtrace_04

5. 观察输出结果

再开一个窗口,mylog.txt中有输出后退出脚本,否则会记录很多无用信息。

postgresql源码学习(50)—— 小白学习Dtrace追踪源码函数调用_源码学习_05

按原文搜一下statistic相关函数,发现有了

cat mylog.txt | sort | uniq | grep -i statistic

postgresql源码学习(50)—— 小白学习Dtrace追踪源码函数调用_Systemtap_06

再看看日志中的内容

postgresql源码学习(50)—— 小白学习Dtrace追踪源码函数调用_postgresql_07

四、 源码学习

定位到函数后,就回到了熟悉的内容,gdb也好vscode也好,可以根据函数名调试和搜索它了。

postgresql源码学习(50)—— 小白学习Dtrace追踪源码函数调用_统计信息_08

postgresql源码学习(50)—— 小白学习Dtrace追踪源码函数调用_postgresql_09

RemoveStatistics函数用于为单表或单列删除pg_statistic系统表中对应的记录。如果attnum为零(未指定列),删除该表的所有记录;如果指定了列,则删除该列的记录。

/*
 * RemoveStatistics --- remove entries in pg_statistic for a rel or column
 *
 * If attnum is zero, remove all entries for rel; else remove only the one(s)
 * for that column.
 */
void
RemoveStatistics(Oid relid, AttrNumber attnum)
{
    Relation    pgstatistic;
    SysScanDesc scan;
    ScanKeyData key[2];
    int         nkeys;
    HeapTuple   tuple;

    pgstatistic = table_open(StatisticRelationId, RowExclusiveLock);

    ScanKeyInit(&key[0],
                Anum_pg_statistic_starelid,
                BTEqualStrategyNumber, F_OIDEQ,
                ObjectIdGetDatum(relid));

    if (attnum == 0)
        nkeys = 1;
    else
    {
        ScanKeyInit(&key[1],
                    Anum_pg_statistic_staattnum,
                    BTEqualStrategyNumber, F_INT2EQ,
                    Int16GetDatum(attnum));
        nkeys = 2;
    }

    scan = systable_beginscan(pgstatistic, StatisticRelidAttnumInhIndexId, true,
                              NULL, nkeys, key);

    /* we must loop even when attnum != 0, in case of inherited stats */
    while (HeapTupleIsValid(tuple = systable_getnext(scan)))
        CatalogTupleDelete(pgstatistic, &tuple->t_self);

    systable_endscan(scan);

    table_close(pgstatistic, RowExclusiveLock);
}

另外看了下会调用该函数的文件

postgresql源码学习(50)—— 小白学习Dtrace追踪源码函数调用_Dtrace_10

点开看了看,大概有以下函数(操作)会删除统计信息:

  • heap_drop_with_catalog - removes specified relation from catalogs,删表
  • RemoveAttributeById - This is the guts of ALTER TABLE DROP COLUMN,删列
  • index_drop - 删索引
  • ATExecAlterColumnType - ALTER COLUMN .. SET DATA TYPE,改字段类型,注释为

/*
     * Drop any pg_statistic entry for the column, since it's now wrong type
     */
    RemoveStatistics(RelationGetRelid(rel), attnum);

 这方法感觉有点傻,应该有更方便能看到函数调用信息的工具?不过暂时没搜到,留待以后吧~

参考

PostgreSQL修改列类型又掉坑了!

使用动态追踪Dtrace分析问题

https://gist.github.com/alexandrnikitin/7fd095371e8c105f6cb9ab7f87664547


举报

相关推荐

0 条评论