本文的目的一是为了备忘,二是为了抛砖引玉,希望有更多的人来研究如何使用好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机制初步学习相关推荐

  1. PostgreSQL的backuplabel file 初步学习

    磨砺技术珠矶,践行数据之道,追求卓越价值 回到上一级页面:PostgreSQL内部结构与源代码研究索引页    回到顶级页面:PostgreSQL索引页 看代码: /* File path names ...

  2. android广播机制初步学习——短信黑名单

    andriod广播机制中主要使用到的两个类:Broadcast和BroadcastReceiver.即一个发送一个接受. 发送的时候是用Intent来携带数据(广播)的,利用Intent中的标识来匹配 ...

  3. PostgreSQL下如何修改用户权限的介绍以及hook机制对超级用户的权限修改

    2019独角兽企业重金招聘Python工程师标准>>> 要想修改PG的用户权限,那么首先要对PG权限控制做一下了解: PG的权限控制是针对到各个对象的.大家可以看一下,所有系统表(p ...

  4. Android 插件化原理学习 —— Hook 机制之动态代理

    前言 为了实现 App 的快速迭代更新,基于 H5 Hybrid 的解决方案有很多,由于 webview 本身的性能问题,也随之出现了很多基于 JS 引擎实现的原生渲染的方案,例如 React Nat ...

  5. 深度理解目标检测(MMdetection)-HOOK机制

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达本文转自|计算机视觉联盟 最近做了一段时间的目标检测,不得不说检测这 ...

  6. Android插件化原理解析——Hook机制之Binder Hook

    Android系统通过Binder机制给应用程序提供了一系列的系统服务,诸如ActivityManagerService,ClipboardManager, AudioManager等:这些广泛存在系 ...

  7. Android 插件化原理解析——Hook机制之AMSPMS

    在前面的文章中我们介绍了DroidPlugin的Hook机制,也就是代理方式和Binder Hook:插件框架通过AOP实现了插件使用和开发的透明性.在讲述DroidPlugin如何实现四大组件的插件 ...

  8. android handler的机制和原理_Android 插件化原理——Hook机制之AMSamp;PMS解析

    在前面的文章中我们介绍了DroidPlugin的Hook机制,也就是代理方式和Binder Hook:插件框架通过AOP实现了插件使用和开发的透明性.在讲述DroidPlugin如何实现四大组件的插件 ...

  9. 初步学习pg_control文件之十四

    接前文 初步学习pg_control文件之十三 看如下几个: /** Parameter settings that determine if the WAL can be used for arch ...

  10. TCP与UDP协议初步学习——网络环境中分布式进程通信的基本概念

    TCP与UDP协议初步学习--网络环境中分布式进程通信的基本概念 一.单机系统中进程通信方法 进程和进程通信是操作系统中最基本的概念,首先通过回忆操作系统课程中,关于单击系统中进程和进程通信的问题描述 ...

最新文章

  1. 深入理解计算机系统——系统级I/O
  2. 计算机启动过程详解二
  3. 对Repository模式误用的反思和纠正
  4. 蚂蚁式管理(Style of Ant Management)
  5. 人人都能够做深度学习应用:入门篇
  6. python3.8使用pyttsx3报错_使用pyttsx3实现python语音播报
  7. qpython3手机版教程,qpython3手机版下载
  8. cv2.imread不能正常读取gif格式图片
  9. Qt解决资源文件中无法显示图片的问题
  10. springboot版本导致Mabatis-Plus报错
  11. OSPF协议邻居(Neighbor)与邻接(Adjacency)关系
  12. down mark 打钩_[MarkDown] markdown语法小结
  13. 入手评测 i7 13700和13700K的区别 i713700和i713700K差距
  14. 美的同一性和神秘的算法分析
  15. 常见网络聊天术语(中英文对照)
  16. 安徽农村信用社网银转账显示服务器无响应,农村信用社企业网银转账显示状态无效是怎么回事...
  17. 智能语音时代,需要了解什么?
  18. 消息中间件(MQ)的相关知识
  19. 用Python通过163邮箱发送邮件
  20. 尤雨溪亲自回应Vue.js涉及国家安全漏洞问题

热门文章

  1. 2017、2018年JS面试题记录分享
  2. KMPlayer怎么加速播放 KMPlayer加速播放方法
  3. 马斯克收购 Twitter 后的 Web3 改革方向
  4. 正则表达式, email格式验证,邮箱地址验证
  5. 如何在zencart里实现多标签标签云效果
  6. 【先锋】永洪科技何春涛:不忘初心,砥砺前行
  7. Spark血缘字段解析
  8. Sql Server 2008 配置服务器,并让客户端连接
  9. 基于 SpringBoot + MyBatis-Plus 的公众号管理系统,接私活必备!
  10. Bing Maps-----微软