systemtap receive strings from address

1 minute read

背景

在PostgreSQL的一些探针中, 有一些是是有target variable的, 即探针触发时可以输出这些变量的值. 例如本文用到的query__done探针, 包含sql string的内存地址信息.

首先要获得target variable变量名, 有两种方法获得, 1是直接看postgresql probe的定义, 如下 :

变量名为arg1.

src/backend/utils/probes.h  
/* TRACE_POSTGRESQL_QUERY_DONE ( const char *) */  
#if defined STAP_SDT_V1  
#define TRACE_POSTGRESQL_QUERY_DONE_ENABLED() __builtin_expect (query__done_semaphore, 0)  
#define postgresql_query__done_semaphore query__done_semaphore  
#else  
#define TRACE_POSTGRESQL_QUERY_DONE_ENABLED() __builtin_expect (postgresql_query__done_semaphore, 0)  
#endif  
__extension__ extern unsigned short postgresql_query__done_semaphore __attribute__ ((unused)) __attribute__ ((section (".probes")));  
#define TRACE_POSTGRESQL_QUERY_DONE(arg1) \  
DTRACE_PROBE1(postgresql,query__done,arg1)  

或者使用systemtap的$$vars来输出可用变量.

[root@db-172-16-3-39 ~]# cat test.stp  
probe process("/home/pg94/pgsql9.4devel/bin/postgres").mark("query__done") {  
  printf("args:%s\n", $$vars)  
  printf("proc:%s, tid:%d, sql:%s\n", execname(), tid(), kernel_string($arg1))  
}  

开启stap :

[root@db-172-16-3-39 ~]# stap test.stp   

在数据库中执行SQL :

digoal=# insert into t9 values (4,'test'),(3,'abc');  
INSERT 0 2  

stap将输出这个event对应的$$vars, 这里的$arg1就是我们要的 :

args:$arg1=0x144f3f60  
proc:postgres, tid:2654, sql:insert into t9 values (4,'test'),(3,'abc');  

接下来要获取query_done这个事件中的target variable arg1的地址对应的string值.

也就是SQL.

[root@db-172-16-3-39 ~]# cat test.stp   
probe process("/home/pg94/pgsql9.4devel/bin/postgres").mark("query__done") {  
  printf("proc:%s, tid:%d, sql:%s\n", execname(), tid(), kernel_string($arg1))  
  exit()  
}  

执行stap

[root@db-172-16-3-39 ~]# stap test.stp  

执行sql :

pg94@db-172-16-3-39-> psql  
psql (9.4devel)  
Type "help" for help.  
digoal=# drop table t9;  
DROP TABLE  
digoal=# create table t9(id int primary key, info text);  
CREATE TABLE  
digoal=# insert into t9 values (1,'test'),(2,'abc');  
INSERT 0 2  
digoal=# \q  

stap输出 :

[root@db-172-16-3-39 ~]# stap test.stp   
proc:postgres, tid:2244, sql:drop table t9;  
proc:postgres, tid:2244, sql:create table t9(id int primary key, info text);  
proc:postgres, tid:2244, sql:insert into t9 values (1,'test'),(2,'abc');  

这里输出了arg1对应地址的字符串, 就是我们要的sql.

使用prepared statement.

digoal=# prepare p1 (int,text) as insert into t9 values ($1,$2);  
PREPARE  
digoal=# execute p1(100,'test');  
INSERT 0 1  
digoal=# execute p1(101,'test');  
INSERT 0 1  
digoal=# execute p1(102,'test');  
INSERT 0 1  
digoal=# execute p1(103,'test');  
INSERT 0 1  
digoal=# execute p1(104,'test');  
INSERT 0 1  
digoal=# execute p1(105,'test');  
INSERT 0 1  
digoal=# execute p1(106,'test');  
INSERT 0 1  

输出 :

[root@db-172-16-3-39 ~]# stap test.stp   
args:$arg1=0x144f3f60  
proc:postgres, tid:2654, sql:prepare p1 (int,text) as insert into t9 values ($1,$2);  
args:$arg1=0x144f3f60  
proc:postgres, tid:2654, sql:execute p1(100,'test');  
args:$arg1=0x144f3f60  
proc:postgres, tid:2654, sql:execute p1(101,'test');  
args:$arg1=0x144f3f60  
proc:postgres, tid:2654, sql:execute p1(102,'test');  
args:$arg1=0x144f3f60  
proc:postgres, tid:2654, sql:execute p1(103,'test');  
args:$arg1=0x144f3f60  
proc:postgres, tid:2654, sql:execute p1(104,'test');  
args:$arg1=0x144f3f60  
proc:postgres, tid:2654, sql:execute p1(105,'test');  
args:$arg1=0x144f3f60  
proc:postgres, tid:2654, sql:execute p1(106,'test');  

虚拟内存地址未变.

digoal=# insert into t9 values (110,'test');  
INSERT 0 1  
digoal=# insert into t9 values (111,'test');  
INSERT 0 1  
digoal=# select * from t9 limit 1;  
 id | info   
----+------  
  1 | test  
(1 row)  

stap输出 :

args:$arg1=0x144f3f60  
proc:postgres, tid:2654, sql:insert into t9 values (110,'test');  
args:$arg1=0x144f3f60  
proc:postgres, tid:2654, sql:insert into t9 values (111,'test');  
args:$arg1=0x144f3f60  
proc:postgres, tid:2654, sql:select * from t9 limit 1;  

参考

1. http://www.postgresql.org/docs/devel/static/dynamic-trace.html

2. https://access.redhat.com/site/documentation/en-US/Red_Hat_Enterprise_Linux/6/html/SystemTap_Tapset_Reference/conversions.stp.html#API-user-string

3. https://sourceware.org/systemtap/tutorial/Analysis.html

Flag Counter

digoal’s 大量PostgreSQL文章入口