PostgreSQL的hook机制初步学习
本文的目的一是为了备忘,二是为了抛砖引玉,希望有更多的人来研究如何使用好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.2/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.2/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) == 0 &&strcmp(username, supersuperuser) != 0)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/MakefileMODULES = dbrestrict OBJS = dbrestreict.soifdef 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 755 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 2013-06-19 21:05:17 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,如果有人可以提供更加详细的信息,十分感谢!
磨砺技术珠矶,践行数据之道,追求卓越价值
本文转自健哥的数据花园博客园博客,原文链接:http://www.cnblogs.com/gaojian/p/3259147.html,如需转载请自行联系原作者
PostgreSQL的hook机制初步学习相关推荐
- PostgreSQL的backuplabel file 初步学习
磨砺技术珠矶,践行数据之道,追求卓越价值 回到上一级页面:PostgreSQL内部结构与源代码研究索引页 回到顶级页面:PostgreSQL索引页 看代码: /* File path names ...
- android广播机制初步学习——短信黑名单
andriod广播机制中主要使用到的两个类:Broadcast和BroadcastReceiver.即一个发送一个接受. 发送的时候是用Intent来携带数据(广播)的,利用Intent中的标识来匹配 ...
- PostgreSQL下如何修改用户权限的介绍以及hook机制对超级用户的权限修改
2019独角兽企业重金招聘Python工程师标准>>> 要想修改PG的用户权限,那么首先要对PG权限控制做一下了解: PG的权限控制是针对到各个对象的.大家可以看一下,所有系统表(p ...
- Android 插件化原理学习 —— Hook 机制之动态代理
前言 为了实现 App 的快速迭代更新,基于 H5 Hybrid 的解决方案有很多,由于 webview 本身的性能问题,也随之出现了很多基于 JS 引擎实现的原生渲染的方案,例如 React Nat ...
- 深度理解目标检测(MMdetection)-HOOK机制
点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达本文转自|计算机视觉联盟 最近做了一段时间的目标检测,不得不说检测这 ...
- Android插件化原理解析——Hook机制之Binder Hook
Android系统通过Binder机制给应用程序提供了一系列的系统服务,诸如ActivityManagerService,ClipboardManager, AudioManager等:这些广泛存在系 ...
- Android 插件化原理解析——Hook机制之AMSPMS
在前面的文章中我们介绍了DroidPlugin的Hook机制,也就是代理方式和Binder Hook:插件框架通过AOP实现了插件使用和开发的透明性.在讲述DroidPlugin如何实现四大组件的插件 ...
- android handler的机制和原理_Android 插件化原理——Hook机制之AMSamp;PMS解析
在前面的文章中我们介绍了DroidPlugin的Hook机制,也就是代理方式和Binder Hook:插件框架通过AOP实现了插件使用和开发的透明性.在讲述DroidPlugin如何实现四大组件的插件 ...
- 初步学习pg_control文件之十四
接前文 初步学习pg_control文件之十三 看如下几个: /** Parameter settings that determine if the WAL can be used for arch ...
- TCP与UDP协议初步学习——网络环境中分布式进程通信的基本概念
TCP与UDP协议初步学习--网络环境中分布式进程通信的基本概念 一.单机系统中进程通信方法 进程和进程通信是操作系统中最基本的概念,首先通过回忆操作系统课程中,关于单击系统中进程和进程通信的问题描述 ...
最新文章
- 深入理解计算机系统——系统级I/O
- 计算机启动过程详解二
- 对Repository模式误用的反思和纠正
- 蚂蚁式管理(Style of Ant Management)
- 人人都能够做深度学习应用:入门篇
- python3.8使用pyttsx3报错_使用pyttsx3实现python语音播报
- qpython3手机版教程,qpython3手机版下载
- cv2.imread不能正常读取gif格式图片
- Qt解决资源文件中无法显示图片的问题
- springboot版本导致Mabatis-Plus报错
- OSPF协议邻居(Neighbor)与邻接(Adjacency)关系
- down mark 打钩_[MarkDown] markdown语法小结
- 入手评测 i7 13700和13700K的区别 i713700和i713700K差距
- 美的同一性和神秘的算法分析
- 常见网络聊天术语(中英文对照)
- 安徽农村信用社网银转账显示服务器无响应,农村信用社企业网银转账显示状态无效是怎么回事...
- 智能语音时代,需要了解什么?
- 消息中间件(MQ)的相关知识
- 用Python通过163邮箱发送邮件
- 尤雨溪亲自回应Vue.js涉及国家安全漏洞问题