PostgreSQL的hook机制初步学习
磨砺技术珠矶,践行数据之道,追求卓越价值
回到上一级页面:PostgreSQL内部结构与源代码研究索引页 回到顶级页面:PostgreSQL索引页
本文的目的一是为了备忘,二是为了抛砖引玉,希望有更多的人来研究如何使用好PostgreSQL的hook机制。
在研究pg_stat_statments的源代码的时候,发现其中使用了hook机制:例如其中提到了如下几种hook:
void
_PG_fini(void)
{
/* Uninstall hooks. */
shmem_startup_hook = prev_shmem_startup_hook;
ExecutorStart_hook = prev_ExecutorStart;
ExecutorRun_hook = prev_ExecutorRun;
ExecutorFinish_hook = prev_ExecutorFinish;
ExecutorEnd_hook = prev_ExecutorEnd;
ProcessUtility_hook = prev_ProcessUtility;
}
hook机制,是一把双刃剑:
它十分强大,可以让用户有机会切入到PostgreSQL的内部运行机制中,完成用户自定义的控制登录过程、查看系统状态、收集数据库活动的统计信息,甚至控制数据库中特定活动的执行。
当然,一般而言要求hook函数用C语言来编写,如果稍有不慎可能造成数据库系统失常乃至崩溃。
如果按照如下的日文网站的列举,其种类繁多,功能丰富:
http://postgresql.g.hatena.ne.jp/pgsql/20090325
遗憾的是,PostgreSQL的官方文档中没有讲如何使用hook的。只是在release note 中隐约提及。
目前,最权威的资料,来自于:http://wiki.postgresql.org/images/e/e3/Hooks_in_postgresql.pdf
为了进行初步的学习,参考了如下的URL的例子:
http://michael.otacoo.com/postgresql-2/hooks-in-postgres-super-superuser-restrictions/
下面描述建立hook的过程:
此处使用的是 ProcessUtility_hook,作为了例子,当我们从psql等发起 drop database xxx命令的时候。
本hook被激活,然后进行检查,如果被删除的数据库名为 fooddb,那么只有用户foo才有机会删除它。
步骤1:建立contrib目录:
[root@server contrib]# pwd
/soft/postgresql-9.1./contrib
[root@server contrib]# mkdir dbrestrict
[root@server contrib]# cd dbrestrict
步骤2:编写程序代码:
需要指出的是,由于我用的是postgresql9.1.2,和上述URL中所用的数据库版本有所不同,故 standard_ProcessUtility 的入口参数有所不同。
[root@server dbrestrict]# pwd
/soft/postgresql-9.1./contrib/dbrestrict
[root@server dbrestrict]# cat dbrestrict.c
/*
* dbrestrict.c
* Restrict drop of a given database to a given super-superuser only.
* Michael Paquier, 2013
* Under license "do whatever you want with that"
*/
#include "postgres.h"
#include "miscadmin.h"
#include "tcop/utility.h" PG_MODULE_MAGIC; void _PG_init(void);
void _PG_fini(void); static char *undroppabledb = "foodb";
static char *supersuperuser = "foo"; static ProcessUtility_hook_type prev_utility_hook = NULL; static void dbrestrict_utility(Node *parsetree, const char *queryString, ParamListInfo params,bool isTopLevel, DestReceiver *dest,char *completionTag); /*
* Personal process for DB drop restriction
*/
static
void dbrestrict_utility(Node *parsetree,const char *queryString,ParamListInfo params,bool isTopLevel,DestReceiver *dest,char *completionTag)
{
/* Do our custom process on drop database */
switch (nodeTag(parsetree))
{
case T_DropdbStmt:
{
DropdbStmt *stmt = (DropdbStmt *) parsetree;
char *username = GetUserNameFromId(GetUserId()); /*
* Check that only the authorized superuser foo can
* drop the database undroppable_foodb.
*/
if (strcmp(stmt->dbname, undroppabledb) == &&
strcmp(username, supersuperuser) != )
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("Only super-superuser \"%s\" can drop database \"%s\"",
supersuperuser, undroppabledb)));
break;
}
default:
break;
} /* Fallback to normal process */
standard_ProcessUtility(parsetree, queryString, params, isTopLevel,dest,completionTag);
} /*
* _PG_init
* Install the hook.
*/
void
_PG_init(void)
{
prev_utility_hook = ProcessUtility_hook;
ProcessUtility_hook = dbrestrict_utility;
} /*
* _PG_fini
* Uninstall the hook.
*/
void
_PG_fini(void)
{
ProcessUtility_hook = prev_utility_hook;
}
[root@server dbrestrict]#
步骤3:建立Makefile:
[root@server dbrestrict]# cat Makefile
# contrib/dbrestrict/Makefile MODULES = dbrestrict
OBJS = dbrestreict.so ifdef USE_PGXS
PG_CONFIG = pg_config
PGXS := $(shell $(PG_CONFIG) --pgxs)
include $(PGXS)
else
subdir = contrib/dbrestrict
top_builddir = ../..
include $(top_builddir)/src/Makefile.global
include $(top_srcdir)/contrib/contrib-global.mk
endif [root@server dbrestrict]#
步骤4:编译和安装:
[root@server dbrestrict]# make
gcc -O2 -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Wendif-labels -Wformat-security -fno-strict-aliasing -fwrapv -fpic -I. -I. -I../../src/include -D_GNU_SOURCE -c -o dbrestrict.o dbrestrict.c
gcc -O2 -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Wendif-labels -Wformat-security -fno-strict-aliasing -fwrapv -fpic -L../../src/port -Wl,-rpath,'/usr/local/pgsql/lib',--enable-new-dtags -shared -o dbrestrict.so dbrestrict.o
rm dbrestrict.o
[root@server dbrestrict]# ls
Makefile dbrestrict.c dbrestrict.so
[root@server dbrestrict]# make install
/bin/mkdir -p '/usr/local/pgsql/lib'
/bin/sh ../../config/install-sh -c -m dbrestrict.so '/usr/local/pgsql/lib/'
[root@server dbrestrict]#
步骤5:配置postgresql.conf文件:把编译好的名为dbrestrict的动态库,追加到 shared_preload_libraries中。
[postgres@server data]$ vim postgresql.conf
[postgres@server data]$ cat postgresql.conf | grep 'preload'
shared_preload_libraries = 'dbrestrict' # (change requires restart)
#local_preload_libraries = ''
[postgres@server data]$
这中 shared_preload_libraries 机制还是不错的,事实上EnterpriseDB PPAS的postgresql.conf的此行是这样的:
shared_preload_libraries = '$libdir/dbms_pipe,$libdir/edb_gen'
步骤6:运行验证:
重新启动postgresql
[postgres@server pgsql]$ ./bin/pg_ctl -D ./data start
server starting
[postgres@server pgsql]$ LOG: loaded library "dbrestrict"
LOG: database system was shut down at -- :: CST
LOG: autovacuum launcher started
LOG: database system is ready to accept connections
可以看到,对用户 foo 和 goo,他们意图drop database foodb时候,得到的信息是不同的;如果foo是super user,就已经可以删除数据库了:
postgres=# create database foodb;
CREATE DATABASE
postgres=# create role foo;
CREATE ROLE
postgres=# \c postgres foo;
FATAL: role "foo" is not permitted to log in
Previous connection kept
postgres=# drop role foo;
DROP ROLE
postgres=# create role foo login;
CREATE ROLE
postgres=# \c postgres foo;
You are now connected to database "postgres" as user "foo".
postgres=> drop database foodb;
ERROR: must be owner of database foodb
postgres=> postgres=# create role goo login;
CREATE ROLE
postgres=# \c postgres goo;
You are now connected to database "postgres" as user "goo". postgres=> drop database foodb;
ERROR: Only super-superuser "foo" can drop database "foodb"
postgres=>
结束!如果有可能,希望更进一步地学习PostgreSQL的各种hook,如果有人可以提供更加详细的信息,十分感谢!
磨砺技术珠矶,践行数据之道,追求卓越价值
回到上一级页面:PostgreSQL内部结构与源代码研究索引页 回到顶级页面:PostgreSQL索引页
PostgreSQL的hook机制初步学习的更多相关文章
- PostgreSQL的backuplabel file 初步学习
磨砺技术珠矶,践行数据之道,追求卓越价值 回到上一级页面:PostgreSQL内部结构与源代码研究索引页 回到顶级页面:PostgreSQL索引页 看代码: /* File path names ...
- Netfilter之连接跟踪实现机制初步分析
Netfilter之连接跟踪实现机制初步分析 原文: http://blog.chinaunix.net/uid-22227409-id-2656910.html 什么是连接跟踪 连接跟踪(CONNT ...
- 初步学习pg_control文件之十四
接前文 初步学习pg_control文件之十三 看如下几个: /* * Parameter settings that determine if the WAL can be used for arc ...
- 初步学习pg_control文件之九
接前文,初步学习pg_control文件之八 来看这个: pg_time_t time; /* time stamp of last pg_control update */ 当初初始化的时候,是这样 ...
- Hook机制里登场的角色
稍有接触过 WordPress 主题或插件制作修改的朋友,对 WordPress 的Hook机制应该不陌生,但通常刚接触WordPress Hook 的新手,对其运作原理可能会有点混乱或模糊.本文针对 ...
- json2.js的初步学习与了解
json2.js的初步学习与了解,想要学习json的朋友可以参考下. json2.js的初步学习与了解 1.)该js的下载地址是:http://www.json.org/json2.js 2.)在页面 ...
- 黄聪:WordPress 的 Hook 机制与原理(add_action、add_filter)
稍有接触过 WordPress 主题或插件制作修改的朋友,对 WordPress 的Hook机制应该不陌生,但通常刚接触WordPress Hook 的新手,对其运作原理可能会有点混乱或模糊.本文针对 ...
- 老周的ABP框架系列教程 -》 一、框架理论初步学习
老周的ABP框架系列教程 -- 一.框架理论初步学习 1. ABP框架的来源与作用简介 1.1 简介 1.1.1 ABP框架全称为"ASP.NET Boilerplate ...
- 初步学习nodejs,业余用node写个一个自动创建目录和文件的小脚本,希望对需要的人有所帮助
初步学习nodejs,业余用node写个一个自动创建目录和文件的小脚本,希望对需要的人有所帮助,如果有bug或者更好的优化方案,也请批评与指正,谢谢,代码如下: var fs = require('f ...
随机推荐
- 对JDBC的轻量级封装,Hibernate框架
IDEA是真的好用... 用脑子下jar包..http://mvnrepository.com/
- C#自定义控件的创建
1.创建自定义控件 选择[经典桌面]——[窗体控件库] 2.添加控件,组合成一个新的控件 自定义控件功能:打开一张图片,将图片展示在pictureBox控件中,并将图片的名称.大小.尺寸显示出来 控件 ...
- 标准的Flask启动文件
最近有一些同学问了我一些项目结构的问题 所以今天给大家专门讲解 解耦后的项目 目录我会分为两种方式:一种是普通解耦 一种是多mvc解耦 首先 我没先建立我们程序的文件夹并且在这个文件夹内写一个和这个文 ...
- 使用NSOperation以及NSOperationQueue
使用NSOperation以及NSOperationQueue NSOperation vs. Grand Central Dispatch (GCD) 在Mac OS X v10.6和iOS4之前, ...
- AT89S52汇编实现l通过按键中断切换led灯的四种闪烁模式(单灯左移,单灯右移,双灯左移,双灯右移)
;通过P1口控制8路LED的四种闪烁模式,单独LED灯左移,单独LED灯右移,相邻两个灯左移,相邻两个灯右移;通过一个外部中断0来检测按键的跳变沿来切换闪烁模式,第一次按键按下弹起,灯的闪烁状态由单独 ...
- PHP设计模式系列 - 中介者模式
中介者模式 中介者模式用于开发一个对象,这个对象能够在类似对象相互之间不直接相互的情况下传送或者调解对这些对象的集合的修改.一般处理具有类似属性,需要保持同步的非耦合对象时,最佳的做法就是中介者模式. ...
- 情绪ABC理论
美国著名心理学家阿尔伯特·艾利斯 [Albert Ellis 1913.09.27]于20世纪50年代创立, 其理论认为引起人们情绪困扰的并不是外界发生的事件,而是人们对事件的态度.看法.评价等认知内 ...
- Hadoop学习之路(十四)MapReduce的核心运行机制
概述 一个完整的 MapReduce 程序在分布式运行时有两类实例进程: 1.MRAppMaster:负责整个程序的过程调度及状态协调 2.Yarnchild:负责 map 阶段的整个数据处理流程 3 ...
- 理解JavaScript继承(二)
理解JavaScript继承(二) 5.寄生式继承 function object(o) { function F() {} F.prototype = o; return new F(); } fu ...
- h5py
解决办法: sudo apt-get install libhdf5-dev sudo apt-get install python-h5py